These are chat archives for RBMHTechnology/eventuate

1st
Aug 2016
Alexander Semenov
@Tvaroh
Aug 01 2016 05:38
Another question: can event handler be asynchronous? I imagine that event handler could run asynchronous operation that returns a function from current state to a next state and then send this function back to the actor wrapped in some class (as a "command" to mutate state) so that state mutation is performed in actor's thread. The only problem is to preserve order of event.
Alexander Semenov
@Tvaroh
Aug 01 2016 06:32
Also, does it make sense to use event handlers to update read model (external db)? I can't use EventsorcedWriter for this since I need to handle errors and notify callers about failures, and in a writer I wouldn't have information to reach a caller (in my main EventsourcedActor I store "responder" objects that I could look up by some connection id and use to send messages to websocket clients).
Maybe I should make my main actor an EventsourcedWriter as well... Or instead allow the writer to ask main actor for some data, like responders...
Alexander Semenov
@Tvaroh
Aug 01 2016 06:44

From EventsourcedWriter example in the docs:

Future.sequence(batch.map(stmt => session.executeAsync(stmt).toFuture))

Is it correct? Statements would be executed in parallel and it would break if one depends on another.

Martin Grotzke
@magro
Aug 01 2016 06:55

can event handler be asynchronous?

An EventsourcedActor is expected to update local (in memory) state, which can be done synchronously. Async operations usually are realized via event collaboration with other event sourced components. Still, I'd say it would technically be possible (even while not the intended usage): when handling an event the async operation is triggered, and the Future response is used to update the internal state of the EventsourcedActor. This requires the async operations to be idempotent because they are executed with at-least-once semantics (on restart events might get replayed the were processed already but didn't receive the async result yet).

does it make sense to use event handlers to update read model (external db)

In fact EventsorcedWriter is supposed to do such a job, or alternatively an EventsorcedProcessor. Events should carry all information that's needed for event processing, I think some time ago there's been a similar discussion here in the chat.
I haven't worked with EventsourcedWriters until now and therefore know them only roughly - perhaps @krasserm or @volkerstampa can provide more/better advice (both are offline these days).

Martin Grotzke
@magro
Aug 01 2016 07:13

From EventsourcedWriter example in the docs ... Statements would be executed in parallel and it would break if one depends on another.

Yes, I also think there might be a race condition - if an AddressUpdated follows a CustomerCreatedwith the same id then there is no guarantee that the CustomerCreated is processed by C* before the AddressUpdated and therefore could overwrite the update (because the INSERT also sets the address). This could probably be resolved with 1) client side timestamps or 2) grouping statements by customer id and write each group as a batch (would be single partition batches and applied in a single operation by the same C* node). Or a simpler example could be used that doesn't come with such potential issues :-)

Alexander Semenov
@Tvaroh
Aug 01 2016 07:13
Martin, I can't validate my commands against in memory state, that's why I need to rely on the result of updating external read model (graph database) for that. So, in an event handler I want to call the db and notify the caller on the wire of the results. That means I can't update in-memory state synchronously (cause graph DB calls are async). Just thinking...
regarding the example, I think it could be solved by executing statements sequentially, not sure if it will play well with Cassandra's eventual consistency though...
Martin Grotzke
@magro
Aug 01 2016 07:18
I'd not couple remote systems with blocking/sync calls, I think documentation should use best/good practices.
Alexander Semenov
@Tvaroh
Aug 01 2016 07:20
no blocking calls, just future1.flatMap(_ => future2.flatMap(_ => ???)) - sequential execution of futures
Martin Grotzke
@magro
Aug 01 2016 07:21

I can't validate my commands against in memory state

Because I don't know anything/much about your domain and the (business) problem that you're trying to solve it's hard to help more high level. Just talking about implementation details is often not the best solution, especially not if there's no understanding of the underlying domain / context.

sequential execution of futures

Right, that would solve it as well.

Alexander Semenov
@Tvaroh
Aug 01 2016 07:22
it's simple, my state is a graph and it would be very painful to have it in-memory too :)
considering all the traversals, indices, etc I need to work with
so, when I'm adding a tree node (within the graph) I would need ideally to validate if its parent exists. But it's only possible by calling the db
so I want just execute DB updates and rely on what it returns for "validation". During events re-play it would re-execute failed calls, but it's not a problem
Martin Grotzke
@magro
Aug 01 2016 07:25
Hmm, ok