Skip to content

Commit 9113597

Browse files
committed
add documentation for EntityBehaviro and entity pattern
1 parent 77556ed commit 9113597

File tree

5 files changed

+315
-16
lines changed

5 files changed

+315
-16
lines changed

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@ The resulting system is highly efficient, with the ability to quickly rebuild it
5050

5151
Moreover, providing the ability to **tag events** enables **read-side projections** to be easily implemented and maintained, improving the overall performance and scalability of the system.
5252

53-
### Event Sourcing with generic-persistence-api
54-
55-
![](docs/diagrams/out/EventSourcing.svg)
53+
### generic-persistence-api
5654

5755
#### Commands
5856

@@ -145,3 +143,28 @@ akka {
145143

146144
![](docs/diagrams/out/Serialization.svg)
147145

146+
##### Versioning
147+
148+
You may find it necessary to change the definition of a particular event type or aggregate at some point in the future.
149+
You must consider how your system will be able to handle multiple versions of an event type and aggregates.
150+
151+
#### Entity Behavior
152+
153+
![](docs/diagrams/out/EntityBehavior.svg)
154+
155+
#### Entity Pattern
156+
157+
As we have seen, Cluster Sharding is a distributed system mechanism in Akka that allows you to partition actor entities across multiple nodes in a cluster. Each entity is uniquely identified by a shard identifier (EntityTypeKey) and an entity identifier.
158+
159+
The shard identifier represents a group of entities that share the same state, and the entity identifier identifies a specific entity within that shard.
160+
161+
When a command is sent to an entity, the "entity pattern" is used to locate the actor reference for that entity. The shard identifier is used to determine which node in the cluster is responsible for managing the shard, and the entity identifier is used to locate the specific actor entity within that shard on that node.
162+
163+
Once the actor reference for the entity has been located, the command is sent to the EntityBehavior, which processes it and updates its state. The state changes are then persisted using Akka Persistence, which ensures that the state changes are durable and can be recovered in the event of a node failure.
164+
165+
![](docs/diagrams/out/Patterns.svg)
166+
167+
### Event Sourcing with generic-persistence-api
168+
169+
![](docs/diagrams/out/EventSourcing.svg)
170+

core/src/main/scala/app/softnetwork/persistence/typed/EntityBehavior.scala

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import akka.persistence.typed.scaladsl.{Effect, EventSourcedBehavior, Recovery,
1010
import app.softnetwork.concurrent.Completion
1111

1212
import app.softnetwork.persistence.message._
13-
import app.softnetwork.persistence.model.{Entity => InternalEntity, _}
13+
import app.softnetwork.persistence.model.{Entity => _, _}
1414
import app.softnetwork.persistence._
1515

1616
import scala.concurrent.duration._
@@ -21,6 +21,12 @@ import scala.reflect.ClassTag
2121
/** Created by smanciot on 16/05/2020.
2222
*/
2323
trait CommandTypeKey[C <: Command] {
24+
25+
/** @param c
26+
* - The type of commands to be send to this type of entity
27+
* @return
28+
* A key that uniquely identifies the type of entity in the cluster
29+
*/
2430
def TypeKey(implicit c: ClassTag[C]): EntityTypeKey[C]
2531
}
2632

@@ -64,27 +70,52 @@ trait EntityEventHandler[S <: State, E <: Event] {
6470

6571
trait EntityBehavior[C <: Command, S <: State, E <: Event, R <: CommandResult]
6672
extends CommandTypeKey[C]
67-
with InternalEntity
73+
with model.Entity
6874
with Completion {
6975
type W = CommandWrapper[C, R] with C
7076

7177
type WR = CommandWithReply[R] with C
7278

73-
/** number of events received before generating a snapshot - should be configurable * */
79+
/** @return
80+
* number of events before saving a snapshot of the current actor entity state. If multiple
81+
* events are persisted with a single Effect the snapshot will happen after all of the events
82+
* are persisted rather than precisely every `numberOfEvents`
83+
*/
7484
def snapshotInterval: Int = 10
7585

86+
/** @return
87+
* number of snapshots to keep
88+
*/
89+
def numberOfSnapshots: Int = 2
90+
91+
/** @return
92+
* the key used to define the Entity Type Key of this actor that uniquely identifies the type
93+
* of entity in this cluster and is then used to retrieve an EntityRef for a given entity
94+
* identifier
95+
*/
7696
def persistenceId: String
7797

7898
/** @return
79-
* node role required to start this actor
99+
* node role required to start this entity actor
80100
*/
81101
def role: String = ""
82102

83103
final def TypeKey(implicit c: ClassTag[C]): EntityTypeKey[C] =
84104
EntityTypeKey[C](s"$persistenceId-$environment")
85105

106+
/** @return
107+
* the intial state for the entity before any events have been processed
108+
*/
86109
val emptyState: Option[S] = None
87110

111+
/** @param system
112+
* - actor system
113+
* @param maybeRole
114+
* - an optional node role required to start this entity
115+
* @param c
116+
* -
117+
* @return
118+
*/
88119
def init(system: ActorSystem[_], maybeRole: Option[String] = None)(implicit
89120
c: ClassTag[C]
90121
): Unit = {
@@ -105,14 +136,17 @@ trait EntityBehavior[C <: Command, S <: State, E <: Event, R <: CommandResult]
105136
*/
106137
def broadcastEvent(event: BE): List[E] = List(event)
107138

108-
/** Set event tags, which will be used in persistence query
139+
/** associate a set of tags to an event before the latter will be appended to the event log
140+
*
141+
* This allows events to be easily filtered and queried based on their tags, improving the
142+
* efficiency of read-side projections
109143
*
110144
* @param entityId
111145
* - entity id
112146
* @param event
113147
* - the event to tag
114148
* @return
115-
* event tags
149+
* set of tags to associate to this event
116150
*/
117151
protected def tagEvent(entityId: String, event: E): Set[String] = Set.empty
118152

@@ -232,7 +266,10 @@ trait EntityBehavior[C <: Command, S <: State, E <: Event, R <: CommandResult]
232266
is fulfilled (snapshotWhen). */
233267
.withRetention(
234268
RetentionCriteria
235-
.snapshotEvery(numberOfEvents = snapshotInterval, keepNSnapshots = 2)
269+
.snapshotEvery(
270+
numberOfEvents = snapshotInterval,
271+
keepNSnapshots = numberOfSnapshots
272+
)
236273
.withDeleteEventsOnSnapshot /* after a snapshot has been successfully stored, a delete of the events
237274
(journaled by a single event sourced actor) up until the sequence number of the data held by that snapshot
238275
can be issued */

0 commit comments

Comments
 (0)