Using ReceiveTimeout in Akka .NET

In Akka .NET, you can opt to receive a special message when an actor is idle (i.e. does not receive any message) for a certain period of time. This message is the ReceiveTimeout, and is particularly useful to clean up idle actors when using the Entity Per Child pattern (although various other scenarios exist where this might be used).

The source code for this article is available at the Gigi Labs BitBucket repository.

Let’s consider an ActorSystem with a single actor. The ActorSystem sends a message to this actor every few seconds, using the built-in Akka .NET Scheduler:

            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                var actor = actorSystem.ActorOf(
                    Props.Create<SomeActor>(), "SomeActor");

                actorSystem.Scheduler.ScheduleTellRepeatedly(
                    initialDelay: TimeSpan.FromSeconds(1),
                    interval: TimeSpan.FromSeconds(5),
                    receiver: actor,
                    message: "Hello!",
                    sender: ActorRefs.NoSender
                );

                Console.ReadLine();
            }

In the actor itself, we call SetReceiveTimeout() in order to be able to receive a ReceiveTimeout message after the specified idle period elapses. Then, we handle the ReceiveTimeout message just like we would handle any other message.

    public class SomeActor : ReceiveActor
    {
        public SomeActor()
        {
            this.Receive<string>(Handle, null);
            this.Receive<ReceiveTimeout>(Handle, null);

            var timeout = TimeSpan.FromSeconds(3);
            this.SetReceiveTimeout(timeout);
        }

        private void Handle(string msg)
        {
            Console.WriteLine(msg);
        }

        private void Handle(ReceiveTimeout msg)
        {
            Console.WriteLine("Timeout received!");
        }
    }

If we run the application with the code we have so far, we get this:

akkanet-receivetimeout-nokill

Although we are handling the ReceiveTimeout message, we aren’t really doing anything to react to it. As the ReceiveTimeout documentation states, the ReceiveTimeout will keep firing after periods of inactivity.

To disable the ReceiveTimeout altogether, just call SetReceiveTimeout() again, passing in null:

this.SetReceiveTimeout(timeout);

You will often want to kill the actor altogether. In particular when using the Entity Per Child pattern, you will want to kill off actors that aren’t in use to keep your memory footprint low; and since you’ll have a parent actor taking care of routing messages and creating child actors as needed, any new message to that actor will cause it to be recreated.

There are different ways to kill an actor, so just pick one and use it in your ReceiveTimeout handler:

        private void Handle(ReceiveTimeout msg)
        {
            Console.WriteLine("Timeout received!");

            Context.Stop(Context.Self); // stop the actor
        }

Since we’re killing the actor now, any subsequent messages become undeliverable:

akkanet-receivetimeout-kill

One thought on “Using ReceiveTimeout in Akka .NET”

Leave a Reply

Your email address will not be published. Required fields are marked *