-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Typed Command Gateway can now be created multiple times per type of a…
…ggregate root (#64)
- Loading branch information
Showing
6 changed files
with
111 additions
and
7 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
97 changes: 97 additions & 0 deletions
97
bounded-core/src/test/scala/io/cafienne/bounded/aggregate/TypedAnotherAggregate.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 | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* Copyright (C) 2016-2021 Cafienne B.V. <https://www.cafienne.io/bounded> | ||
*/ | ||
|
||
package io.cafienne.bounded.aggregate | ||
|
||
import akka.actor.typed.Behavior | ||
import akka.cluster.sharding.typed.scaladsl.EntityTypeKey | ||
import akka.persistence.typed.PersistenceId | ||
import akka.persistence.typed.scaladsl.{Effect, EventSourcedBehavior, ReplyEffect} | ||
import com.typesafe.scalalogging.Logger | ||
import io.cafienne.bounded.aggregate.typed.TypedAggregateRootManager | ||
import scala.concurrent.duration._ | ||
import akka.actor.typed.scaladsl.{Behaviors, TimerScheduler} | ||
import akka.persistence.RecoveryCompleted | ||
|
||
//This another aggregate is for testing the use of command gateways with multiple aggregates. | ||
object TypedAnotherAggregate { | ||
val aggregateRootTag = "ar-another" | ||
import TypedSimpleAggregate._ | ||
|
||
var replayed = false | ||
|
||
final val logger = Logger(TypedSimpleAggregate.getClass.getSimpleName) | ||
|
||
|
||
// Command handler logic | ||
def commandHandler( | ||
timers: TimerScheduler[SimpleAggregateCommand] | ||
): (SimpleAggregateState, SimpleAggregateCommand) => ReplyEffect[SimpleAggregateEvent, SimpleAggregateState] = { | ||
(state, command) => | ||
logger.debug("Received command: " + command) | ||
command match { | ||
case cmd: Create => createAggregate(cmd) | ||
case cmd: AddItem => addItem(cmd) | ||
case cmd: Stop => | ||
logger.debug("Stopping Aggregate {}", cmd.aggregateRootId) | ||
Effect.stop().thenReply(cmd.replyTo)(_ => OK) | ||
case cmd: StopAfter => | ||
timers.startSingleTimer( | ||
InternalStop(aggregateRootId = cmd.aggregateRootId, metaData = cmd.metaData), | ||
2.seconds | ||
) | ||
Effect.none.thenReply(cmd.replyTo)(_ => OK) | ||
case cmd: InternalStop => | ||
logger.debug("InternalStop for aggregate {}", cmd.aggregateRootId) | ||
Effect.stop().thenNoReply() | ||
} | ||
} | ||
|
||
private def createAggregate(cmd: Create): ReplyEffect[SimpleAggregateEvent, SimpleAggregateState] = { | ||
logger.debug(s"Create Aggregate (replayed: $replayed)" + cmd) | ||
Effect.persist(Created(cmd.aggregateRootId, TestMetaData.fromCommand(cmd.metaData))).thenReply(cmd.replyTo)(_ ⇒ OK) | ||
} | ||
|
||
private def addItem(cmd: AddItem): ReplyEffect[SimpleAggregateEvent, SimpleAggregateState] = { | ||
logger.debug("AddItem " + cmd) | ||
Effect | ||
.persist(ItemAdded(cmd.aggregateRootId, TestMetaData.fromCommand(cmd.metaData), cmd.item)) | ||
.thenReply(cmd.replyTo)(_ ⇒ OK) | ||
} | ||
|
||
// event handler to keep internal aggregate state | ||
val eventHandler: (SimpleAggregateState, SimpleAggregateEvent) => SimpleAggregateState = { (state, event) => | ||
logger.debug("updating state with {}", event) | ||
state.update(event) | ||
} | ||
|
||
} | ||
|
||
import TypedSimpleAggregate._ | ||
class AnotherAggregateManager() extends TypedAggregateRootManager[SimpleAggregateCommand] { | ||
import TypedSimpleAggregate._ | ||
final val logger = Logger(this.getClass.getSimpleName) | ||
|
||
override def behavior(id: String): Behavior[SimpleAggregateCommand] = { | ||
logger.debug("Create aggregate behavior for {}", id) | ||
Behaviors.withTimers { timers ⇒ | ||
EventSourcedBehavior | ||
.withEnforcedReplies( | ||
PersistenceId(aggregateRootTag, id), | ||
SimpleAggregateState(List.empty[String]), | ||
commandHandler(timers), | ||
eventHandler | ||
) | ||
.receiveSignal { | ||
case (state, b: RecoveryCompleted) => { | ||
logger.debug("Received RecoveryCompleted for actor with state {}", state) | ||
replayed = true | ||
} | ||
} | ||
} | ||
} | ||
|
||
override def entityTypeKey: EntityTypeKey[SimpleAggregateCommand] = | ||
EntityTypeKey[SimpleAggregateCommand](aggregateRootTag) | ||
} |
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
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 | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
|
||
version in ThisBuild := "0.3.1" | ||
version in ThisBuild := "0.3.2" |