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!

4

1 回答 1

0

另一种方法是将两个事件同时保存在您的聚合中,但这假设聚合具有可用的信息。如果第二个计算依赖于一堆查询端数据,那么这当然不是一个选项。

但是,如果您只是因为其他子系统感兴趣而这样做,那么这听起来确实超出了聚合的范围。您可以将非持久事件发布到事件流并让其他视图/侦听器订阅。

于 2014-08-12T16:57:30.950 回答