-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#43: added support for overlapping persisters using a marker interface #46
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,14 @@ package stamina | |
|
||
import scala.reflect._ | ||
import scala.util._ | ||
import scala.reflect.runtime.universe.{Try ⇒ uTry, _} | ||
|
||
/** | ||
* A Persister[T, V] provides a type-safe API for persisting instances of T | ||
* at version V and unpersisting persisted instances of T for all versions up | ||
* to and including version V. | ||
*/ | ||
abstract class Persister[T: ClassTag, V <: Version: VersionInfo](val key: String) { | ||
abstract class Persister[T: ClassTag, V <: Version: VersionInfo](val key: String)(typeTagOption: Option[TypeTag[T]] = None) { | ||
lazy val currentVersion = Version.numberFor[V] | ||
|
||
def persist(t: T): Persisted | ||
|
@@ -18,8 +19,17 @@ abstract class Persister[T: ClassTag, V <: Version: VersionInfo](val key: String | |
def canUnpersist(p: Persisted): Boolean = p.key == key && p.version <= currentVersion | ||
|
||
private[stamina] def convertToT(any: AnyRef): Option[T] = any match { | ||
case t: T ⇒ Some(t) | ||
case _ ⇒ None | ||
case t: T ⇒ t match { | ||
case tagged: TypeTagged[_] if typeTagOption.isDefined ⇒ | ||
val typeTag = tagged.tag | ||
val currentTypeTag = typeTagOption.get.tpe.toString | ||
typeTag.tpe.toString match { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're comparing the String represenations of the type tags here. Would comparing with |
||
case `currentTypeTag` ⇒ Some(t) | ||
case _ ⇒ None | ||
} | ||
case _ ⇒ Some(t) | ||
} | ||
case _ ⇒ None | ||
} | ||
|
||
private[stamina] def persistAny(any: AnyRef): Persisted = { | ||
|
@@ -37,5 +47,9 @@ abstract class Persister[T: ClassTag, V <: Version: VersionInfo](val key: String | |
} | ||
} | ||
|
||
private[stamina] val tag = classTag[T] | ||
private[stamina] val tag = typeTagOption.map(_.tpe).getOrElse(classTag[T].runtimeClass) | ||
} | ||
|
||
object Persister { | ||
implicit def optionTypeTag[E](implicit typeTag: TypeTag[E]) = Some(typeTag) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package stamina | ||
|
||
import scala.reflect.runtime.universe._ | ||
|
||
/** | ||
* This marker interface can be used to solve the problem of nested json formats of the same | ||
* root format. | ||
* By example: | ||
* trait Event[E] { | ||
* } | ||
* | ||
* case class Payload1() | ||
* case class Payload2() | ||
* | ||
* The Persister cannot distinguish Event[Payload1] from Event[Payload2] due to type erasure within | ||
* Akka serialization to AnyRef. Therefore you can mark your Event envelop using a TypeTagged marker | ||
* interface which whould allow stamina to choose the correct persister for the kind of event payload | ||
* which should get serialized. | ||
*/ | ||
class TypeTagged[X: TypeTag] extends AnyRef { | ||
@transient val tag = typeTag[X] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,18 @@ | ||
package stamina | ||
|
||
import scala.reflect._ | ||
import akka.actor._ | ||
import akka.serialization._ | ||
import scala.reflect.ClassTag | ||
import scala.reflect.runtime.universe._ | ||
|
||
object TestOnlyPersister { | ||
private val system = ActorSystem("TestOnlyPersister") | ||
private val javaSerializer = new JavaSerializer(system.asInstanceOf[ExtendedActorSystem]) | ||
import javaSerializer._ | ||
|
||
def persister[T <: AnyRef: ClassTag](key: String): Persister[T, V1] = new JavaPersister[T](key) | ||
def persister[T <: AnyRef: ClassTag](key: String)(implicit typeTag: TypeTag[T] = null): Persister[T, V1] = new JavaPersister[T](key)(Option(typeTag)) | ||
|
||
private class JavaPersister[T <: AnyRef: ClassTag](key: String) extends Persister[T, V1](key) { | ||
private class JavaPersister[T <: AnyRef: ClassTag](key: String)(typeTagOption: Option[TypeTag[T]] = None) extends Persister[T, V1](key)(typeTagOption) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, this line now triggers a warning:
Not sure what that's about, as it definitely appears to be still in use... |
||
def persist(t: T): Persisted = Persisted(key, currentVersion, toBinary(t)) | ||
def unpersist(p: Persisted): T = { | ||
if (canUnpersist(p)) fromBinary(p.bytes.toArray).asInstanceOf[T] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are different versions of scala-reflect binary compatible?