Actor supervisors in Akka.NET FSharp API

This post will describe changes, that will affect a F# API for Akka.NET in the incoming versions of the framework (>= 0.62) – mostly those, which concerns supervisioning and manipulating actor hierarchies.

I don’t want to overload this post with explaining what Akka supervision is all about, so I’ll just recommend a very good article, which could be found here.

While previous versions of the Akka F# API introduced some nice features such as function-based actor definitions and creations (spawn function), there still was no simple way to handle some core framework concepts. Remember that march towards Akka.NET 1.0 is still in progress, more and more features are implemented. Therefore it’s F# API most likely will also be a subject to change.

To give a better description of the new features, lets see an example:

let strategy =
    Strategy.oneForOne (fun e ->
        match e with
        | :? ArithmeticException -> Directive.Resume
        | :? ArgumentException -> Directive.Stop
        | _ -> Directive.Escalate)

let supervisor =
    spawnOpt system "master" (fun mailbox ->
        // by using spawn we may create a child actors without exiting a F# functional API
        let worker = spawn mailbox "worker" workerFun

        let rec loop() =
            actor {
                let! msg = mailbox.Receive()
                match msg with
                | Respond -> worker.Tell(msg, mailbox.Sender())
                | _ -> worker <! msg
                return! loop()
            }
        loop()) [ SupervisorStrategy(strategy) ]

A whole example is available inside Akka.NET project source code, along with other examples.

Unlike standard spawn, spawnOpt function could take a list of options used to configure spawned actor internals. SupervisorStrategy is one of them. By using F# API you are able to use Strategy module to quickly create a corresponding strategy instance. It supports two types of strategy creators:

  1. Strategy.oneForOne – strategy will affect only an exception thrower.
  2. Strategy.allForOne – strategy result will propagate to all children of the actor implementing that strategy.

Both functions come in two variants. First one takes only one argument – decider function, which determines an expected behavior based upon type of exception thrown. Second one (Strategy.oneForOne2 and Strategy.allForOne2) precedes decider argument with a timeout and number of possible behavior retries. All of them corresponds directly to standard Akka strategy API, but are wrapped to fit F# functional approach instead of method overrides.