0

I am implementing an EventSourcing application that handles a large number of original and derived data points. In short, we have an PersistentActor functioning as an Aggregate Root accepting commands:

UpdateValue(name, value, timestamp)
UpdateValue(name, value, timestamp)
UpdateValue(name, value, timestamp)

After these commands are verified, they produce events which are persisted and update the state:

ValueUpdated(name, value, timestamp)
ValueUpdated(name, value, timestamp)
ValueUpdated(name, value, timestamp)

In a PersistentView we listen to these events and calculate derived values:

case v @ ValueUpdated("value_i_care_about", _, _) => calculate_derived_values(v)
case v @ ValueUpdated("another_value_i_care_about", _, _) => calculate_derived_values(v)

But this recalculation itself is a new value on which other views could depend, so that means that we have to send a new command back to the aggregate root to process the new value, which can produce events that can be picked up by this or other views.

Is it acceptable for a view to produce events or commands? I would think a view's responsibility is to update a state based on events, not produce events or commands. Also, the order in which events arrive can influence the new events being broadcast during replay.

Is it necessary to produce commands instead of events? Since the command was updating the initial value, you could argue that producing all the derived values are simply events that are the result of the command being processed, although they are generated in a distributed fashion and not directly by the aggregate root.

I've been looking at Akka's Reactive Streams that could be used to string these actors together, and also looked at the idea of Sagas as presented here: http://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-i-of-ii/. In that post Jonathan mentions:

Sagas listen to events and dispatch commands while aggregates receive commands and publish events.

That seems like a sensible approach as well, to implement all these actors as FSMs: wait 5 seconds for related events, recalculate everything, dispatch command, wait 5 seconds for events, etc.

To make things a little bit more interesting, the streams of values can be out of order and incomplete, but should produce derived values at points in time. So if I receive values A & B:

  • A1, B1, B2, A2, B3, A4, B4

it should produce derived values D:

  • D1 (A1 * B1), D2 (B2 * A2), D3 (B3 * A2, there is no A3), D4 (A4 * B4)

This means I have to keep track of order, and sometimes reissue a derived value if a missing value comes in.

Thanks!

Kamiel Wanrooij
  • 12,164
  • 6
  • 37
  • 43
  • 1
    Wouldn't you be better off considering that once the first `PersistentView` has been updated, you're no longer in the realm of DDD and you must find a Read-Model-technology specific way of propagating changes through your views ? Are those recalculation events really Events in the DDD sense of the word ? – guillaume31 Aug 01 '14 at 13:05
  • Well, no, probably those derived calculations are just state changes that occur based on the first event, not events in itself. I tried storing the original events in the views so I could recalculate the derived values, but that becomes really tedious after the third or fourth level of derived values (basically the views all just contain a complete snapshot of all related data at that point.). – Kamiel Wanrooij Aug 03 '14 at 17:23

2 Answers2

0

An alternative is to persist both events at once in your aggregate but this assumes the aggregate has the information available to do so. If the second calculation relies on a bunch of query side data then of course this isn't an option.

But truly this sounds outside of the realm of the aggregate if you are doing it simply because other subsystems are interested. You can just publish a non-persistent event to the event stream and have other views/listeners subscribe.

SeanW
  • 26
  • 2
0

This question apparently (from the references to PersistentView) is based on an older version of Akka Persistence.

In more recent (at least back to 2.5) Akka Persistence, this sort of functionality is handled by persistence queries, which expose streams (in this use case, you would typically use the non-terminating streams (those which don't have current in their names)) of events. In those streams, there's no real restriction on what you can do: it's perfectly valid to project the events as commands against some other aggregate (which effectively makes that aggregate, from the perspective of the source aggregate a read-model of that source aggregate). If doing this, you will probably want to use the ask pattern to propagate backpressure to the query.

It's worth noting that an event is implicitly a command to anything which sees the event: "incorporate this event into your view of the world". As a command, it can be rejected (equivalent to ignoring the event which is not denying the event).

Levi Ramsey
  • 18,884
  • 1
  • 16
  • 30