Lutando
Lutando

Reputation: 5010

How to do queries on a collection of actors

I have an actor system that at the moment accepts commands/messages. The state of these actors is persisted Akka.Persistance. We now want to build the query system for this actor system. Basically our problem is that we want to have a way to get an aggregate/list of all the states of these particular actors. While I'm not strictly subscribing to the CQRS pattern I think that it might be a neat way to go about it.

My initial thoughts was to have an actor for querying that holds as part of its state an aggregation of the states of the other actors that are doing the "data writes". And to do this this actor will subscribe to the actors its interested to and these actors would just send the query actor their states when they undergo some sort of state change. Is this the way to go about this? is there a better way to do this?

Upvotes: 4

Views: 1335

Answers (2)

Bartosz Sypytkowski
Bartosz Sypytkowski

Reputation: 7542

Some of Akka.Persistence backends (i.e. those working with SQL) also implement something known as Akka.Persistence.Query. It allows you to subscribe to a stream of events that are produced, and use this as a source for Akka.Streams semantics.

If you're using SQL-journals you'll need Akka.Persistence.Query.Sql and Akka.Streams packages. From there you can create a live (that means continuously updated) source of events for a particular actor and use it for any operations you like i.e print them:

using (var system = ActorSystem.Create("system"))
using (var materializer = system.Materializer())
{
    var queries = Sys.ReadJournalFor<SqlReadJournal>(SqlReadJournal.Identifier)

    queries.EventsByPersistenceId("<persistence-id>", 0, long.MaxValue)
        .Select(envelope => envelope.Event)
        .RunForEach(e => Console.WriteLine(e), materializer);
}

Upvotes: 1

Aaronontheweb
Aaronontheweb

Reputation: 8394

My recommendation for implementing this type of pattern is to use a combination of pub-sub and push-and-pull messaging for your actors here.

For each "aggregate," this actor should be able to subscribe to events from the individual child actors you want to query. Whenever a child's state changes, a message is pushed into all subscribed aggregates and each aggregate's state is updated automatically.

When a new aggegrate comes online and needs to retrieve state it missed (from before it existed) it should be able to pull the current state from each child and use that to build its current state, using incremental updates from children going forward to keep its aggregated view of the children's state consistent.

This is the pattern I use for this sort of work and it works well locally out of the box. Over the network, you may have to ensure deliverability guarantees and that's generally easy to do. You can read a bit more on how to do that there: https://petabridge.com/blog/akkadotnet-at-least-once-message-delivery/

Upvotes: 1

Related Questions