These are chat archives for RBMHTechnology/eventuate

10th
Feb 2016
Martin Krasser
@krasserm
Feb 10 2016 05:35
@Tvaroh have you seen EventsourcedWriter? Regarding reply to the user: you reply when the event has been successfully persisted with an EventsourcedActor and rely on the EventsourcedWriter to reliably update the database from written events. The EventsourcedActor should maintain a write model that can be used for command validation.
Alexander Semenov
@Tvaroh
Feb 10 2016 06:04
@krasserm yes, that's exactly my understanding. But what if the writer can't perform the insert due to some issues, e.g. uniqueness constraints violation?
maintaining write model in memory would mean to have all the database content in memory, that's probably not an option
one idea is to reply with "accepted" response from the command (eventual consistency) and allow to somehow request that command's events processing status (were they succeeded on not)
but that complicates the clients
Martin Krasser
@krasserm
Feb 10 2016 06:46
@Tvaroh I would suspect an issue in application design then. For example, with UserCreated(userId, ...) events which add a row in a User table of a query database, you can get uniqueness constraints violations when you are re-using userIds, for example. In this case the application should ensure that userIds are uniquely generated. Obtaining a unique userId should be done during command validation. Furthermore, having the write model in-memory doesn't require all the DB content in memory. Here, you'd only need userIds in memory or have them managed by an external userId generator which can even be the target database from which you could request new userIds.
Alexander Semenov
@Tvaroh
Feb 10 2016 06:50
@krasserm thanks, you're right, I will revisit the design
Alexander Semenov
@Tvaroh
Feb 10 2016 06:56
One more example: I'm persisting an entity that has a relation to another entity, e.g. adding a child node to a tree node. I get parent node id from the user. What if the parent is removed just before the writer persists the child node? I could validate parent node existence in command handler but it leaves the possibility for the parent to be removed after that validation before event handler is called.
Martin Krasser
@krasserm
Feb 10 2016 08:54
@Tvaroh you're trying to achieve strong consistency in a CQRS setup with eventual consistency. If you need strong consistency between the command-side (C) and the query-side (Q) then you are probably on the wrong path with an approach that asynchronously propagates changes from C to Q. On the other hand, it might be OK from an application logic perspective if the writer just ignores a failed node insertion if the parent node has been deleted meanwhile. Alternatively, you could maintain a lightweight shape of the tree as write model to make command validation with strong consistency (within the boundary of an EventsourcedActor)
Alexander Semenov
@Tvaroh
Feb 10 2016 09:01
I agree with "it might be OK from an application logic perspective if the writer just ignores a failed node insertion if the parent node has been deleted meanwhile" and this is my intent. But the reply I sent from command to the client then would make client state and server state diverge. Or client should somehow check command processing result.
Martin Krasser
@krasserm
Feb 10 2016 09:03
@Tvaroh unless you're using an appropriate write model ...
Alexander Semenov
@Tvaroh
Feb 10 2016 09:04
yep, exactly
Alexander Semenov
@Tvaroh
Feb 10 2016 09:16
Would that approach work for multiple EventsourcedActors in different locations using same eventlog? There could be a race while that change is propagated to other locations even if I check parent existence in command handler.
Martin Krasser
@krasserm
Feb 10 2016 09:19
@Tvaroh that's the whole story about Eventuate: when you replicate an EventsourcedActor you need to relax strong consistency to causal consistency and deal with races by by tracking, detecting and resolving conflicts (see user guide).
Alexander Semenov
@Tvaroh
Feb 10 2016 09:21
@krasserm thanks will refresh this stuff with new understanding
Alexander Semenov
@Tvaroh
Feb 10 2016 12:28
@krasserm in the conflict resolution example you use rather simplistic versioned state of type ConcurrentVersions[Vector[String], String] that can only append elements. But what if the state is more complicated data structure with nested maps, lists, etc that allows to add, remove, update parts of its structure? Looks like it would require versioned state of type ConcurrentVersions[ComplicatedStateType, CommandType] so that is could be updated correctly depending on command type. Am I right?
Martin Krasser
@krasserm
Feb 10 2016 12:34
@Tvaroh yes, except that it's ConcurrentVersions[ComplexStateType, EventType]
Alexander Semenov
@Tvaroh
Feb 10 2016 12:53
ah, right
Martin Krasser
@krasserm
Feb 10 2016 13:32
@Tvaroh also take a look at the example application for a slightly more complex example.
Alexander Semenov
@Tvaroh
Feb 10 2016 13:32
@krasserm nice, thanks so much!
Alexander Semenov
@Tvaroh
Feb 10 2016 13:50
@krasserm Is VersionedAggregate purpose described somewhere in docs?
Martin Krasser
@krasserm
Feb 10 2016 13:52
Only in the API docs
Alexander Semenov
@Tvaroh
Feb 10 2016 13:52
I see