Concepts: Event Sourced State

Joe Hegarty edited this page May 2, 2016 · 2 revisions

Overview

Event Sourced state stores the history of an Actor’s state by recording Events which changed the Actor’s state.

Events can be replayed to recover the current valid state for the Actor.

Working with Event Sourcing

Adding State

Adding Event Souced state to an actor in Orbit is simple. Developers simply extend EventSourceActor in place of AbstractActor, passing a generic which extends TransactionalState as the state object.

As with Active Record, the state object must be serializeable.

public class StatefulActor extends EventSourcedActor<StatefulActor.State> implements Some
{
    public static class State extends TransactionalState
    {
        int balance;
    }
}

Adding Events

Unlike Active Record, state changes when using Event Sourced state must be made using Events.

Events are replayable actions which modify the internal state of the Actor.

Events must be annotated with TransactionalEvent, must be not be conditional and must always be able to succeed.

public class StatefulActor extends EventSourcedActor<StatefulActor.State> implements Some
{
    public static class State
    {
        int balance;

        @TransactionalEvent
        void incrementBalance(int amount)
        {
             balance += amount;
        }
    }
}

Retrieving State

Like Active record, Event Sourced state is automatically retrieved when an actor is activated.

Developers can also manually re-retrieve the state using the readState method.

public Task doReadState()
{
    await(readState());
    // New state is accessible here 
    return Task.done();
}

Accessing State

Accessing Event Sourced state in a stateful actor is simple and works exactly the same as Active Record. The state method provides access to the current state.

public Task doSomeState()
{
    System.out.println(state().lastMessage);
    return Task.done();
}

Executing an Event

In order to make changes to and Event Sourced Actor’s state, you must execute an event.

public Task incrementUserBalance(int amount)
{
    state().incrementBalance(amount);
    return Task.done();
}

Writing State

The writing of Event Sourced state is identical to Active Record and is determined only by developers, Orbit will not automatically write state.

public Task doWriteState()
{
    return writeState();
}

Clearing State

While actors are never created or destroyed in Orbit, developers can choose to clear an actors state if they wish.

public Task doClearState()
{
    return clearState();
}

Writing State On Deactivation

Sometimes it is desirable to write state on actor deactivation, this ensures that the latest state is persisted once the actor has been deactivated.

@Override
public Task deactivateAsync()
{
    await(writeState());
    return super.deactivateAsync();
}