-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prepare Eventsourced and Generic Akka Runtime for production use (#44)
- Loading branch information
Showing
42 changed files
with
485 additions
and
224 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
modules/akka-cluster-runtime/src/main/protobuf/GenericAkkaRuntime.proto
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,12 @@ | |||
syntax = "proto2"; | |||
|
|||
package aecor.runtime.akkageneric.serialization; | |||
option java_package = "aecor.runtime.akkageneric.serialization.msg"; | |||
option optimize_for = SPEED; | |||
|
|||
message KeyedCommand { | |||
required string key = 1; | |||
required bytes bytes = 2; | |||
} | |||
|
|||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
...akka-cluster-runtime/src/main/scala/aecor/runtime/akkageneric/serialization/Message.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,6 @@ | |||
package aecor.runtime.akkageneric.serialization | |||
|
|||
/** | |||
* Marker trait for all protobuf-serializable messages in `aecor.runtime.akkageneric`. | |||
*/ | |||
private[akkageneric] trait Message |
65 changes: 65 additions & 0 deletions
65
...er-runtime/src/main/scala/aecor/runtime/akkageneric/serialization/MessageSerializer.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,65 @@ | |||
package aecor.runtime.akkageneric.serialization | |||
|
|||
import java.nio.ByteBuffer | |||
|
|||
import aecor.runtime.akkageneric.GenericAkkaRuntime.KeyedCommand | |||
import aecor.runtime.akkageneric.GenericAkkaRuntimeActor.{ Command, CommandResult } | |||
import akka.actor.ExtendedActorSystem | |||
import akka.serialization.{ BaseSerializer, SerializerWithStringManifest } | |||
import com.google.protobuf.ByteString | |||
|
|||
import scala.collection.immutable.HashMap | |||
|
|||
class MessageSerializer(val system: ExtendedActorSystem) | |||
extends SerializerWithStringManifest | |||
with BaseSerializer { | |||
|
|||
val KeyedCommandManifest = "A" | |||
val CommandManifest = "B" | |||
val CommandResultManifest = "C" | |||
|
|||
private val fromBinaryMap = | |||
HashMap[String, Array[Byte] ⇒ AnyRef]( | |||
KeyedCommandManifest -> keyedCommandFromBinary, | |||
CommandManifest -> commandFromBinary, | |||
CommandResultManifest -> commandResultFromBinary | |||
) | |||
|
|||
override def manifest(o: AnyRef): String = o match { | |||
case KeyedCommand(_, _) => KeyedCommandManifest | |||
case Command(_) => CommandManifest | |||
case CommandResult(_) => CommandResultManifest | |||
case x => throw new IllegalArgumentException(s"Serialization of [$x] is not supported") | |||
} | |||
|
|||
override def toBinary(o: AnyRef): Array[Byte] = o match { | |||
case Command(bytes) => | |||
bytes.array() | |||
case CommandResult(bytes) => | |||
bytes.array() | |||
case x @ KeyedCommand(_, _) => | |||
entityCommandToBinary(x) | |||
case x => throw new IllegalArgumentException(s"Serialization of [$x] is not supported") | |||
} | |||
|
|||
override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = | |||
fromBinaryMap.get(manifest) match { | |||
case Some(f) => f(bytes) | |||
case other => throw new IllegalArgumentException(s"Unknown manifest [$other]") | |||
} | |||
|
|||
private def entityCommandToBinary(a: KeyedCommand): Array[Byte] = | |||
msg.KeyedCommand(a.key, ByteString.copyFrom(a.bytes)).toByteArray | |||
|
|||
private def keyedCommandFromBinary(bytes: Array[Byte]): KeyedCommand = | |||
msg.KeyedCommand.parseFrom(bytes) match { | |||
case msg.KeyedCommand(key, commandBytes) => | |||
KeyedCommand(key, commandBytes.asReadOnlyByteBuffer) | |||
} | |||
|
|||
private def commandFromBinary(bytes: Array[Byte]): Command = | |||
Command(ByteBuffer.wrap(bytes)) | |||
|
|||
private def commandResultFromBinary(bytes: Array[Byte]): CommandResult = | |||
CommandResult(ByteBuffer.wrap(bytes)) | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
.../src/main/scala/aecor/runtime/akkapersistence/readside/CommittableEventJournalQuery.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 16 additions & 3 deletions
19
...sistence-runtime/src/main/scala/aecor/runtime/akkapersistence/readside/JournalQuery.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ersistence-runtime/src/main/scala/aecor/runtime/akkapersistence/readside/Projection.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,44 @@ | |||
package aecor | |||
|
|||
trait Has[T, A] { | |||
def get(t: T): A | |||
def contramap[D](f: D => T): Has[D, A] = Has.instance[D](x => get(f(x))) | |||
} | |||
|
|||
object Has extends TupleInstances { | |||
def apply[A, T](implicit instance: Has[T, A]): Has[T, A] = instance | |||
|
|||
final class Builder[T] { | |||
@inline def apply[A](f: T => A): Has[T, A] = new Has[T, A] { | |||
override def get(t: T): A = f(t) | |||
} | |||
} | |||
def instance[T]: Builder[T] = new Builder[T] | |||
|
|||
implicit def refl[A]: Has[A, A] = instance[A](identity) | |||
implicit def hasTuple[A, B, T](implicit TA: Has[T, A], TB: Has[T, B]): Has[T, (A, B)] = | |||
instance[T](x => (TA.get(x), TB.get(x))) | |||
|
|||
trait HasSyntax { | |||
implicit def toHasSyntaxIdOps[A](a: A): HasSyntaxIdOps[A] = new HasSyntaxIdOps(a) | |||
} | |||
|
|||
final class HasSyntaxIdOps[T](val a: T) extends AnyVal { | |||
def get[X](implicit T: Has[T, X]): X = T.get(a) | |||
} | |||
object syntax extends HasSyntax | |||
} | |||
|
|||
trait TupleInstances { | |||
implicit def tuple2HasA[X, A, B](implicit AX: Has[A, X]): Has[(A, B), X] = | |||
Has.instance[(A, B)](x => AX.get(x._1)) | |||
implicit def tuple2HasB[X, A, B](implicit BX: Has[B, X]): Has[(A, B), X] = | |||
Has.instance[(A, B)](x => BX.get(x._2)) | |||
|
|||
implicit def tuple3HasA[X, A, B, C](implicit AX: Has[A, X]): Has[(A, B, C), X] = | |||
Has.instance[(A, B, C)](x => AX.get(x._1)) | |||
implicit def tuple3HasB[X, A, B, C](implicit BX: Has[B, X]): Has[(A, B, C), X] = | |||
Has.instance[(A, B, C)](x => BX.get(x._2)) | |||
implicit def tuple3HasC[X, A, B, C](implicit CX: Has[C, X]): Has[(A, B, C), X] = | |||
Has.instance[(A, B, C)](x => CX.get(x._3)) | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,5 +1,14 @@ | |||
package aecor.data | package aecor.data | ||
|
|
||
import aecor.Has | |||
|
|||
final case class EntityEvent[I, A](entityId: I, sequenceNr: Long, payload: A) { | final case class EntityEvent[I, A](entityId: I, sequenceNr: Long, payload: A) { | ||
def map[B](f: A => B): EntityEvent[I, B] = copy(payload = f(payload)) | def map[B](f: A => B): EntityEvent[I, B] = copy(payload = f(payload)) | ||
} | } | ||
|
|||
object EntityEvent { | |||
implicit def aecorHasInstanceForId[X, I, A](implicit I: Has[I, X]): Has[EntityEvent[I, A], X] = | |||
Has.instance[EntityEvent[I, A]](x => I.get(x.entityId)) | |||
implicit def aecorHasInstanceForValue[X, I, A](implicit A: Has[A, X]): Has[EntityEvent[I, A], X] = | |||
Has.instance[EntityEvent[I, A]](x => A.get(x.payload)) | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.