I'm interested how to apply CQRS and Event Sourcing with Akka.net. I already noticed Akka.Persistence which delivers the ES part.
As far as I understand the Command Handlers and AggergateRoot can be represented by the ReceivePersistentActor in a single class. I have a base class for that (not complete here)...
public abstract class AggregateRoot<TState> : ReceivePersistentActor
{
private readonly Func<TState, bool> shouldSafeSnapShot;
protected AggregateRoot(TState state, Func<TState, bool> shouldSafeSnapShot)
{
if (state == null) throw new ArgumentNullException(nameof(state));
if (shouldSafeSnapShot == null) throw new ArgumentNullException(nameof(shouldSafeSnapShot));
var path = this.Self.Path;
this.PersistenceId = $"{path.Parent.Name}/{path.Name}";
this.State = state;
this.shouldSafeSnapShot = shouldSafeSnapShot;
}
public sealed override string PersistenceId { get; }
protected TState State { get; }
protected void Emit<TEvent>(TEvent e, Action<TEvent> apply = null)
{
this.Persist(e,
@event =>
{
// update state
apply?.Invoke(@event);
// safe snapshot or so...
this.SaveSnapshotIfRequired();
// publish to event bus?
Context.System.EventStream.Publish(e);
});
}
private void SaveSnapshotIfRequired()
{
var state = this.State;
if (this.shouldSafeSnapShot(state))
{
this.SaveSnapshot(state);
}
}
}
Not I want to send the event over the EventBus and Akka seems to bring something within it's package that might fit to the way it is done with other CQRS frameworks (EventBus abstractions in NCqrs, Inceptum) or in the simple sample of Gregory Young here.
// publish to event bus?
Context.System.EventStream.Publish(e);
However, it seems weird to me to know the implementation of the eventbus within the AggregateRoot domain object actor. I could put the responsibility to an actor child or inject something like an IAbstractEventBus interface that is used to switch implementations but I don't think it should be the responsibility of the AggregateRoot to publish the event after persisting and inform all subscribers, right!? But the ES part seems to be coupled to the Actor.
What is the typical way to do that with Akka.net and Akka.Persistence? Any design ideas how to split this up?
I stumbled up the IEventAdapter interface of Akka.net but I'm not sure this brings me to the right path (or dark side)...
public class SomeEventAdapter : IEventAdapter
{
public object ToJournal(object evt)
{
return evt; // should I add the event emitter here?
// but is this already stored now? hmmm
}
}