Switchable Actor Behaviour in Akka.NET

One of the things that actors can do is change their behaviour in response to an incoming message. This doesn’t however mean that we end up with a single “god actor” that has too many responsibilities. Whilst this may also seem like a potentially dangerous thing to do it is actually a very poweful concept. Because an actor instance only processes one message at a time, we don’t have to worry about this behaviour switch affecting the currently processing message, in fact the change in behaviour applies to the next message processed.

There’s a number of benefits to using switchable behaviours including the potential reduction/simplification of the amount of code we need to write and the ability for our brains to conceptualize what the the actor does more readily.

As an example, consider the following code that represents an actor that can respond in one of two ways to an incoming message depending on its current (boolean) state:

class LightSwitchActor : ReceiveActor
{
    private bool _isTurnedOn;
    public LightSwitchActor()
    {
        Receive<FlipTheSwitchMessage>(message => HandleMessage(message));
    }

    private void HandleMessage(FlipTheSwitchMessage message)
    {
        if (_isTurnedOn)
        {
            // do some processing when currently turned on and message received

            // flip the switch
            _isTurnedOn = false;
        }
        else
        {
            // do some processing when currently turned off and message received

            // flip the switch
            _isTurnedOn = true;
        }
    }
}

In the preceding code, the state of the boolean field _isTurnedOn determines how the actor behaves in response to an incoming FlipTheSwitchMessage.

This actor could be refactored so that the isTurnedOn field is removed and the different behavioural states become more explicit:

class LightSwitchBehaviourActor : ReceiveActor
{
    public LightSwitchBehaviourActor()
    {
        TurnedOff();   
    }


    private void TurnedOn()
    {
        Receive<FlipTheSwitchMessage>(
            message =>
            {
                // do some processing when currently turned on and message received                            

                // flip the switch
                Become(TurnedOff);
            });
    }

    private void TurnedOff()
    {
        Receive<FlipTheSwitchMessage>(
            message =>
            {
                // do some processing when currently turned off and message received                                  

                // flip the switch
                Become(TurnedOn);
            });
    }
}

Note the use of the Become() method which allows us to change how we respond to the next message that gets processed.

Whilst in these simple examples there are only two states (TurnedOn and TurnedOff) an actor could describe a greater number of potentially more complex behaviours.

For more information check out the Akka.NET docs or my Pluralsight course: Building Concurrent Applications with the Actor Model in Akka.NET.

SHARE:

Pingbacks and trackbacks (3)+

Add comment

Loading