@@ -28,7 +28,10 @@ import scala.concurrent.duration.DurationInt
2828
2929import akka .actor .typed .scaladsl .ActorContext
3030import akka .actor .typed .scaladsl .Behaviors
31+ import akka .persistence .typed .internal .EventSourcedBehaviorImpl .GetSeenSequenceNr
32+ import akka .persistence .typed .internal .EventSourcedBehaviorImpl .GetVersion
3133import akka .persistence .typed .internal .ReplicatedEventMetadata
34+ import akka .persistence .typed .internal .VersionVector
3235import akka .persistence .typed .scaladsl .EventWithMetadata
3336
3437object ReplicatedEventSourcingSpec {
@@ -238,17 +241,136 @@ class ReplicatedEventSourcingSpec
238241
239242 r1 ! StoreMe (" 2 from r1" , probe.ref)
240243 r2 ! StoreMe (" 2 from r2" , probe.ref)
244+ r2 ! StoreMe (" 3 from r2" , probe.ref)
241245
242246 eventually {
243247 val probe = createTestProbe[State ]()
244248 r1 ! GetState (probe.ref)
245- probe.expectMessageType[State ].all.toSet shouldEqual Set (" 1 from r1" , " 1 from r2" , " 2 from r1" , " 2 from r2" )
249+ val expected = Set (" 1 from r1" , " 1 from r2" , " 2 from r1" , " 2 from r2" , " 3 from r2" )
250+ probe.expectMessageType[State ].all.toSet shouldEqual expected
246251 r2 ! GetState (probe.ref)
247- probe.expectMessageType[State ].all.toSet shouldEqual Set ( " 1 from r1 " , " 1 from r2 " , " 2 from r1 " , " 2 from r2 " )
252+ probe.expectMessageType[State ].all.toSet shouldEqual expected
248253 }
249254 }
250255 }
251256
257+ " recover version and seenSeqNrPerReplica" in {
258+ val entityId = nextEntityId
259+ val r1Behavior = testBehavior(entityId, " R1" )
260+ val r2Behavior = testBehavior(entityId, " R2" )
261+ val probe = createTestProbe[Done ]()
262+
263+ def assertFirst (r1 : ActorRef [Command ], r2 : ActorRef [Command ]): Unit = {
264+ val seenSeqNrProbe = createTestProbe[Long ]()
265+ r1.unsafeUpcast[Any ].tell(GetSeenSequenceNr (ReplicaId (" R1" ), seenSeqNrProbe.ref))
266+ seenSeqNrProbe.receiveMessage() shouldEqual 0L // not tracking self
267+ r1.unsafeUpcast[Any ].tell(GetSeenSequenceNr (ReplicaId (" R2" ), seenSeqNrProbe.ref))
268+ seenSeqNrProbe.receiveMessage() shouldEqual 0L // no events from R2 yet
269+
270+ r2.unsafeUpcast[Any ].tell(GetSeenSequenceNr (ReplicaId (" R1" ), seenSeqNrProbe.ref))
271+ seenSeqNrProbe.receiveMessage() shouldEqual 2L
272+ r2.unsafeUpcast[Any ].tell(GetSeenSequenceNr (ReplicaId (" R2" ), seenSeqNrProbe.ref))
273+ seenSeqNrProbe.receiveMessage() shouldEqual 0L // not tracking self
274+
275+ val versionProbe = createTestProbe[VersionVector ]()
276+ r1.unsafeUpcast[Any ].tell(GetVersion (versionProbe.ref))
277+ val v1 = versionProbe.receiveMessage()
278+ v1.versionAt(" R1" ) shouldEqual 2L
279+ v1.versionAt(" R2" ) shouldEqual 0L
280+
281+ r2.unsafeUpcast[Any ].tell(GetVersion (versionProbe.ref))
282+ val v2 = versionProbe.receiveMessage()
283+ v2.versionAt(" R1" ) shouldEqual 2L
284+ v2.versionAt(" R2" ) shouldEqual 0L
285+ }
286+
287+ {
288+ // first incarnation, only persist in R1
289+ val r1 = spawn(r1Behavior)
290+ val r2 = spawn(r2Behavior)
291+ r1 ! StoreMe (" 1 from r1" , probe.ref)
292+ r1 ! StoreMe (" 2 from r1" , probe.ref)
293+
294+ eventually {
295+ val probe = createTestProbe[State ]()
296+ r1 ! GetState (probe.ref)
297+ val expected = Set (" 1 from r1" , " 2 from r1" )
298+ probe.expectMessageType[State ].all.toSet shouldEqual expected
299+ r2 ! GetState (probe.ref)
300+ probe.expectMessageType[State ].all.toSet shouldEqual expected
301+ }
302+
303+ assertFirst(r1, r2)
304+
305+ r1 ! Stop
306+ r2 ! Stop
307+ probe.expectTerminated(r1)
308+ probe.expectTerminated(r2)
309+ }
310+
311+ def assertSecond (r1 : ActorRef [Command ], r2 : ActorRef [Command ]): Unit = {
312+ val seenSeqNrProbe = createTestProbe[Long ]()
313+ r1.unsafeUpcast[Any ].tell(GetSeenSequenceNr (ReplicaId (" R1" ), seenSeqNrProbe.ref))
314+ seenSeqNrProbe.receiveMessage() shouldEqual 0L // not tracking self
315+ r1.unsafeUpcast[Any ].tell(GetSeenSequenceNr (ReplicaId (" R2" ), seenSeqNrProbe.ref))
316+ seenSeqNrProbe.receiveMessage() shouldEqual 5L
317+
318+ r2.unsafeUpcast[Any ].tell(GetSeenSequenceNr (ReplicaId (" R1" ), seenSeqNrProbe.ref))
319+ seenSeqNrProbe.receiveMessage() shouldEqual 2L
320+ r2.unsafeUpcast[Any ].tell(GetSeenSequenceNr (ReplicaId (" R2" ), seenSeqNrProbe.ref))
321+ seenSeqNrProbe.receiveMessage() shouldEqual 0L // not tracking self
322+
323+ val versionProbe = createTestProbe[VersionVector ]()
324+ r1.unsafeUpcast[Any ].tell(GetVersion (versionProbe.ref))
325+ val v1 = versionProbe.receiveMessage()
326+ v1.versionAt(" R1" ) shouldEqual 2L
327+ v1.versionAt(" R2" ) shouldEqual 5L
328+
329+ r2.unsafeUpcast[Any ].tell(GetVersion (versionProbe.ref))
330+ val v2 = versionProbe.receiveMessage()
331+ v2.versionAt(" R1" ) shouldEqual 2L
332+ v2.versionAt(" R2" ) shouldEqual 5L
333+ }
334+
335+ {
336+ // second incarnation, only persisting in R2
337+ val r1 = spawn(r1Behavior)
338+ val r2 = spawn(r2Behavior)
339+
340+ // should recover to the same
341+ assertFirst(r1, r2)
342+
343+ r2 ! StoreMe (" 1 from r2" , probe.ref)
344+ r2 ! StoreMe (" 2 from r2" , probe.ref)
345+ r2 ! StoreMe (" 3 from r2" , probe.ref)
346+
347+ eventually {
348+ val probe = createTestProbe[State ]()
349+ r1 ! GetState (probe.ref)
350+ val expected = Set (" 1 from r1" , " 2 from r1" , " 1 from r2" , " 2 from r2" , " 3 from r2" )
351+ probe.expectMessageType[State ].all.toSet shouldEqual expected
352+ r2 ! GetState (probe.ref)
353+ probe.expectMessageType[State ].all.toSet shouldEqual expected
354+ }
355+
356+ assertSecond(r1, r2)
357+
358+ r1 ! Stop
359+ r2 ! Stop
360+ probe.expectTerminated(r1)
361+ probe.expectTerminated(r2)
362+ }
363+
364+ {
365+ // third incarnation
366+ val r1 = spawn(r1Behavior)
367+ val r2 = spawn(r2Behavior)
368+
369+ // should recover to the same
370+ assertSecond(r1, r2)
371+ }
372+ }
373+
252374 " have access to replica information" in {
253375 val entityId = nextEntityId
254376 val probe = createTestProbe[(ReplicaId , Set [ReplicaId ])]()
@@ -709,4 +831,5 @@ class ReplicatedEventSourcingSpec
709831 stateProbe.expectMessage(State (Vector (" FROM R1" , " from r2" )))
710832 }
711833 }
834+
712835}
0 commit comments