Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Akka's persistent actor, is creating a child actor considered to be a side effect, or the creation of state?

This question isn't as philosophical as the title might suggest. Consider the following approach to persistence:

Commands to perform Operations come in from various Clients. I represent both Operations and Clients as persistent actors. The Client's state is the lastOperationId to pass through. The Operation's state is pretty much an FSM of the Operation's progress (it's effectively a Saga, as it then needs to reach out to other systems external to the ActorSystem in order to move through it's states).

A Reception actor receives the operation command, which contains the client id and operation id. The Reception actor creates or retrieves the Client actor and forwards it the command. The Client actor reads and validates the operation command, persists it, creates an OperationReceived event, updates its own state with the this operation id. Now it needs to create a new Operation actor to manage the new long-running operation. But here is where I get lost and all the nice examples in the documentation and on the various blogs don't help. Most commentators say that a PersistentActor converts commands to events, and then updates their state. They may also have side effects as long as they are not invoked during replay. So I have two areas of confusion:

  1. Is the creation of an Operation actor in this context equivalent to creating state, or performing a side effect? It doesn't seem like a side effect, but at the same time it's not changing its own state, but causing a state change in a new child.
  2. Am I supposed to construct a Command to send to the new Operation actor or will I simply forward it the OperationReceived event?

If I go with my assumption that creating a child actor is not a side effect, it means I must also create the child when replaying. This in turn would cause the state of the child to be recovered.

I hope the underlying question is clear. I feel it's a general question, but the best way I can formulate it is by giving a specific example.

Edit: On reflection, I think that the creation of one persistent actor from another is an act of creating state, albeit outsourced. That means that the event that triggers the creation will trigger that creation on a subsequent replay (which will lead to the retrieval of the child's own persisted state). This makes me think that passing the event (rather than a wrapping command) might be the cleanest thing to do as the same event can be applied to update the state in both parent and child. There should be no need to persist the event as it comes into the child - it has already been persisted in the parent and will replay.

like image 932
Brendan Avatar asked Jan 14 '15 20:01

Brendan


People also ask

What is the difference between a normal and persistent Akka actor?

In a normal Akka.NET actor, all of an actor’s state exists as internal fields within an actor class declaration. In a persistent Akka.NET actor, we still have our application state in-memory - but our actors recover it on restart from a durable store by replaying messages and aggregates of messages from our persistent store.

What is Akka’s implementation via event sourced actors?

What follows is Akka’s implementation via event sourced actors. An event sourced actor (also known as a persistent actor) receives a (non-persistent) command which is first validated if it can be applied to the current state.

How does Akka persist work?

That’s no accident - Akka.Persistence is driven heavily by configuration (more on that in a moment) and abstracts away the details of which database it’s storing messages to and how those messages are represented in the store. The Persist method call is what causes the persistent actor to journal each new string message into the configured store.

How to use Akka persistence with JVM?

You also have to select journal plugin and optionally snapshot store plugin, see Persistence Plugins. Akka Persistence enables stateful actors to persist their state so that it can be recovered when an actor is either restarted, such as after a JVM crash, by a supervisor or a manual stop-start, or migrated within a cluster.


1 Answers

On reflection, I think that the creation of one persistent actor from another is an act of creating state, albeit outsourced. That means that the event that triggers the creation will trigger that same creation on a subsequent replay. This makes me think that passing the event (rather than a wrapping command) might be the cleanest thing to do as the same event can be applied to update the state in both parent and child. There should be no need to persist the event as it comes into the child - it has already been persisted in the parent and will replay.

like image 71
Brendan Avatar answered Sep 28 '22 11:09

Brendan