Skip to content
This repository has been archived by the owner on Jun 1, 2021. It is now read-only.

One aggregate per actor pattern #36

Closed
krasserm opened this issue Feb 25, 2015 · 3 comments
Closed

One aggregate per actor pattern #36

krasserm opened this issue Feb 25, 2015 · 3 comments
Assignees
Milestone

Comments

@krasserm
Copy link
Contributor

Efficiently support the pattern to have one DDD Aggregate per EventsourcedActor. The example application still follows the many aggregates per actor pattern but it has already been re-written by @remcobeckers to follow the one aggregate per actor pattern (see also this discussion). Eventuate should support efficient implementations of this pattern by providing the following enhancements:

  • the event log must be indexed by aggregate id for efficient recovery of individual aggregates
  • if an aggregate actor writes an event, the event log should only notify those aggregate actor replicas with the same aggregate id (and not all other actors subscribed to the event log). Nevertheless, EventsourcedViews or non-aggregate EventsourcedActors continue to receive all events written to the event log (to support the one view for many actors pattern, for example).
  • implement EventsourcedAggregate as specialization of EventsourcedActor to support implementing the one aggregate per actor pattern. Update: EventsourcedActor has an optional aggregateId.
  • consider implementing aggregate services similar to CRDT services to free applications from dealing with low-level details.
  • the one aggregate per actor prototype is already implemented in a way that vector clock sizes scale with the number of replicas only instead of the potentially large number of aggregates. Ensure that an implementation of EventsourcedAggregate cannot break this property.
@remcobeckers
Copy link

I didn't have time yet to write this up, so awesome you already took the time! I couldn't have put it more accurate. If all of this is supported it would reduce the amount of code needed for one aggregate per actor to the minimum I think.

I was initially thinking of implementing a VersionedObject (for a single aggregate) similar to the VersionedObjects which I have been heavily borrowing from to implement the one aggregate per actor in the example. I think offering an EventsourcedAggregate is a better idea. With that the boilerplate needed can be reduced further and the intended usage is much clearer. A VersionedObject might be useful in building the EventsourcedAggregate though.

@krasserm
Copy link
Contributor Author

@remcobeckers no worries!

Glad that the summary fits your requirements. I agree, something like VersionedObject should be part of the implementation as well. Not only for EventsourcedAggregate but also for re-use in views.

I still need to complete some other tickets first but hope to be able to start working on this soon.

krasserm added a commit that referenced this issue Mar 2, 2015
- re #36
- Optional aggregate id in EventsourcedActor
- Breaking change: processId -> replicaId
- EventsourcedActors with no aggregate id defined receive all events
- EventsourcedActors with aggregate id defined receive events from replicas with same aggregate id
- Eventlog not indexed yet (still full scan for aggregate replays)
- Scala example re-written
@krasserm
Copy link
Contributor Author

krasserm commented Mar 2, 2015

@remcobeckers I just committed a first implementation supporting the one-aggregate-per-actor pattern. It introduces an optional aggregateId to EventsourcedActor. If aggregateId is not defined, the actor receives all events from the event log (backwards compatibility). If aggregateId is defined, the actor only receives events from EventsourcedActor replicas with the same aggregate id (isolating aggregate actors from each other). Replicas are identified with a replicaId (replacing the processId). Replica ids must be unique within the context of an aggregate id.

I did not introduce a separate EventsourcedAggregate. This wasn't necessary but could be easily done by applications to require an aggregate id, for example. The Scala example application is re-written and applies the new pattern, the Java example still uses the old n-aggregates-per-actor pattern but I'll rewrite that later too.

The event log is not indexed yet, so an aggregate recovery is a full log scan at the moment but this is an implementation details in the event log. The index will come with one of the next commits (together with user doc and API doc updates and further tests).

Would be great if you could take a look at the commit and let me know if it fits your requirements.

Cheers,
Martin

@krasserm krasserm added this to the 0.1 milestone Mar 4, 2015
@krasserm krasserm self-assigned this Mar 4, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants