These are chat archives for RBMHTechnology/eventuate

3rd
Dec 2016
Marco Ehrentreich
@mehrentreich
Dec 03 2016 10:08 UTC
hey guys
can someone give me a hint what would be the correct design to execute an action with side-effects as a reaction to a domain event that has happend but only on the first occurrence of the event?
that meas the action should no be triggered when events are replayed
what I want to do is to collect information from a few events (probably in an EventsourcedView)
and when a specific event has happened I want to use these information to send a notification email
obviously I don't want to re-send the email everytime events are replayed ;-)
but unfortunately I don't have any good ideas how I could achieve this with Akka / Eventuate
Martin Krasser
@krasserm
Dec 03 2016 10:12 UTC
use the condition !recovering in the event handler for at-most-once semantics or use ConfirmedDelivery to let another actor execute the side effect with at-least-once semantics
Marco Ehrentreich
@mehrentreich
Dec 03 2016 10:13 UTC
@krasserm great! thx a lot!
Martin Krasser
@krasserm
Dec 03 2016 10:16 UTC
Regarding email integration, maybe you want to take a look at the akka streams adapter and the new Camel integration in Streamz. Camel provides components for SMTP/IMAP/...
I plan to use the akka streams adapter - streamz combo a lot in the future :smiley:
Marco Ehrentreich
@mehrentreich
Dec 03 2016 10:17 UTC
ok, sounds very interesting
Marco Ehrentreich
@mehrentreich
Dec 03 2016 10:22 UTC
so much to learn, so little time :-)
but really great stuff
Juan Ramón González
@jrgonzalezg
Dec 03 2016 12:19 UTC

Thanks, @mehrentreich My idea is that if actors are indeed cheap (which they seem to be in terms of cpu / thread usage), and i have a read model (Eventsourcedview) that uses a "big" chunk of memory, i could probably obtain better/cheaper scalability if i can have more cpu capacity working on the same shared in-memory (immutable) data structure, computing several queries concurrently. The relocation of the data from memory to a separate database (or elastic search as you suggest) could be a way to do that since that would then be the "only" place containing the shared query state (although in that setup the query results will still need additional memory on each actor). But it seems a bit of an overkill for me because i expect the data that needs to be used for these queries to be a fairly constant 100-200mb in size and that could easily fit on memory leading to faster and cheaper queries with less latency.

The problem is that if i need to fully clone the Eventsourcedview actor(s) then the scaling of cpu and the scaling of the memory will be tightly coupled and i would need a replica of that 100-200mb for scaling cpu by adding additional actors. So even if actors are lighter than threads, the memory usage with that approach will still lead to bad scalability. From my research i found some places saying that sharing mutable actor state is a bad practice (http://manuel.bernhardt.io/2016/08/02/akka-anti-patterns-shared-mutable-state/) and there are also issues with the actor location (since shared state will not work across locations). But if the shared state is not mutable (or delays on the mutations to propagate to all queries are not important) it does not seem like a bad idea to me to have additional copies of the state only on different locations and have several actors sharing state at the same location / node.

Maybe i try to optimize too much :D, but i have been googling about this on the past few hours and it seems like Akka Agents (http://doc.akka.io/docs/akka/current/scala/agents.html) and ScalaSTM (http://nbronson.github.io/scala-stm/) may be a way to do this.

For now i think i will just start trying some implementations until i find one that goes well enough...

Juan Ramón González
@jrgonzalezg
Dec 03 2016 12:36 UTC
Just found this!: http://doc.akka.io/docs/akka/current/general/jmm.html#actors-and-shared-mutable-state This is very interesting too, it seems that certain uses of Future are ok to do and if that "expensiveCalculation()" is done in parallel with new messages / commands (i am not sure if it really works that way) it may be easier and clearer than what i said before...
Volker Stampa
@volkerstampa
Dec 03 2016 13:15 UTC
@jrgonzalezg If it makes sense to maintain multiple read models, one for normal search queries and one for id queries probably depends on the requirements regarding the search criteria in both use cases. If the criteria are pretty much the same (i.e. requires the same sort of indexing) a single read model is probably enough, but if different types of indexing is required it can make sense to maintain two read models.
However a simplified write model might also make sense. Regarding the write model I would in general let the transactional or consistency boundaries be the guiding principle. If this is defined by your locations I guess it makes sense to have an aggregate per location.
As you already found out it is in general not a good idea to share mutable state by multiple actors to handle concurrent queries. However a single actor (EventsourcedView) could maintain the read model in an immutable data structure and return a reference to it on request so that the actual query execution can be done on this data structure outside of the actor and thus concurrently. Keep in mind that snapshots might be required for such a view to keep replay times short when the event log grows. The alternative of a persistent view (as proposed by @mehrentreich ) maintained through an EventsourcedWriter would not require snapshots.
Marco Ehrentreich
@mehrentreich
Dec 03 2016 13:35 UTC
@jrgonzalezg I'm not an expert but from my understanding one of the core principles behind the actor model is to make concurrency easy by avoiding shared (mutable) state
so even if it may be technically possible to write an application based on actors which do share state it may be a sign that either the architecture and design you have envisioned for your application is not really appropriate for an actor-based solution or actors may even be the wrong tool for your problem at hand
but of course it's hard to tell without knowing all the little details ;-)
someone may correct me if I'm wrong
Juan Ramón González
@jrgonzalezg
Dec 03 2016 15:24 UTC

Thanks @volkerstampa! that actually looks like a very good design. Just to clarify what you explain: if an actor replies a message with a reference to the query structure, only the reference is passed around with no serialization / deserialization involved and no additional copies being made of the structure? I haven't learned how Akka implements the message passing internally, but if it is optimized to only pass a reference to the same memory (when possible due to actor location) that could actually be perfect for my use case.

For the snapshots vs EventsourcedWriter i have not a sufficiently clear idea yet of what i need but i will certainly study both options. It may even be enough to just use replayFromSequenceNr for some of the views i have (in particular the view that needs to have info about all the aggregates for querying) because i think i do not need events older than some "close" date for that specific query view and it may be possible to know / store which sequence number corresponds to that date and replay only from that point forward. So i guess i will probably need at the end a combination of snapshots, sequence numbers and (maybe) persistent views for different parts of the project or different microservices.

Juan Ramón González
@jrgonzalezg
Dec 03 2016 15:32 UTC
@mehrentreich i do not think there is a problem at all with using the actor model for my use case. At the end the design of Eventuate allows so many different views and stream transformations as needed and the worse that could happen is that some functionality or some queries may need to be handled by accessing a persistent view or external database directly instead of just an EventsourcedView with an in-memory state. But, in fact, Eventuate provides mechanisms like the EventsourcedWriter to do that too, so i do not think it is a wrong tool :)
Juan Ramón González
@jrgonzalezg
Dec 03 2016 16:58 UTC
@volkerstampa Found a nice talk about the implementation of Akka with respect to state here and while serialization / deep copies are also possible it can work without making copies (it even seems to be the default), so i would definitely use your suggestion