Skip to content
Bartosz Sypytkowski edited this page Feb 25, 2016 · 3 revisions

While native Akka.NET API is pretty dynamic at the moment, it doesn't provide much type safety. One of the Akkling goals is to introduce a tiny layer over it, which allows to describer actor's behavior and communicate with them with compile time safety guarantees.

You've might already seen that most of Akkling API operates on IActorRef<'Message> actor references - they are basic constructs, that erasure type of messages passed at compile time. Each of the spawning functions returns typed refs in result. In case, when you want to interop with native Akka.NET IActorRefs, you may easily convert them to typed versions using typed function.

In addition you may communicate with actors using following operators (all of them provide static type checking):

  • (<!) (actorRef : #ICanTell<'Message>) (msg : 'Message) : unit - tell operator, sends a message to target actor through it's actor ref.
  • (<<!) (actorRef : #IActorRef<'Message>) (msg : 'Message) : unit - forward operator, send a message to target actor through it's actor ref, but unlike <!, it doesn't override message sender.
  • (<?) (tell : #ICanTell<'Message>) (msg : 'Message) : Async<AskResult<'Response>> - ask operator, sends a message to target actor through it's actor ref and returns F# Async, which completes, once recipient will send back a response. Response timeout may be configured through HOCON using akka.actor.ask-timeout setting (WARNING: timeout is infinite by default).
  • (|!>) (computation : Async<'Message>) (recipient : ICanTell<'Message>) - pipeTo operator, asynchronously waits for an Async operation to complete and sends it's result as a message to target actor, using it's actor ref. This operator comes in two versions: left-side <!| and right-side |!>.

Sometimes it's not easy to describe correct actor ref message types to be handled, as you may need to combine your own type hierarchy with Akka system messages. This would result in actor ref always handling Object as the only common "denominator" between these two. For this you may decide to use retype function which is able to convert IActorRef<'A>IActorRef<'B>, when it's necessary. This may also be used to narrow/widen message types available to be send through actor ref for any reason necessary.

Actor selections

Sometimes you don't have an actor ref, which you could use to send message to an actor, however you can provide logical path to target actor. In this case you can use following function:

  • select (selector : IActorRefFactory) (path : string) : TypedActorSelection<'Message> - result is typed actor selection, that can be used to communicate with actor.

In Akkling, selections are as type safe as any other actor ref. You can also use operators defined above on them. You can also use actor selections to retrieve actor refs if necessary. Below you can see one of the ways, how to do so:

async {
    let selection = select system "akka.tcp://remote-system@localhost:4000/user/parent/child"
    let! reply = selection <? Identify("correlation-id")
    match reply with
    | ActorIdentity("correlation-id", Some(ref)) -> ref <! "ok" // found
    | _ -> () // not found
} 

Remember that this operation may also end with timeout, as there will be no actor system to respond this call.