Cricket


Actor Lookup

ActorPaths

Actor Paths are a simply a string that identifies an actor or a group of actors. They look and work much like a web address. An example of an actor path might be something like the following

actor.tcp://actorHost1@192.168.1.90:8080/models/stats/average

This path is broken down into the following components.

{protocol}://{host name}@{protocol address}/{local path}
  • Protocol - This defines which protocol actors should use to talk to each other. Local actors will simply use the actor protocol. When the actor is a remote actor then this portion will be replaced with the scheme of the message that the transport was recieved on. For example if the message was received on the TcpActorProtocol then this portion of the path will be set to actor.tcp

  • Host Name - This identifies the host that the actor was created in. The host name can be set when calling ActorHost.Start(..)

  • Protocol Address - Typically you will simply let the framework resolve this for you. As the exact structure of this will depend on the underlying transport. In the example above we are using the actor.tcp transport so the IP address an port are required for this transport; However another example maybe a message queue based protocol in which case this may define the topic or queue name.

  • Local Path - This is the name that was given to the actor when it was defined.

At first look Actor paths can seem quite verbose, but in truth it is a rare occasion when we need to specify a fully qualified path like the one above. Typically we can just get away with specifying the local path portion, for example

/models/stats/average

This path is a pointer to ALL actors on ALL nodes with that name. For example if there where 5 nodes all with an actor registered /models/stats/average then resolving this will lead to 5 fully qualified actor paths

[
    actor.tcp://actorhost1@192.168.1.90:8080/models/stats/average
    actor.tcp://actorhost2@192.168.1.90:8081/models/stats/average
    actor.tcp://actorhost3@192.168.1.90:8082/models/stats/average
    actor.tcp://actorhost4@192.168.1.90:8083/models/stats/average
    actor.tcp://actorhost5@192.168.1.90:8084/models/stats/average
]

This is all fine, but what if there are several actors all under a different name, is it possible to reference them all with a single path? Answer: Yes, but the local path needs some structure. When the local path of the actor is defined, it is defined like any path. This path is used to build a tree.

models
   |
   |--- stats
          |
          |--- average

so to be able to match different types of actors we need a common root. Given,

[
    /models/stats/mean
    /models/stats/stddev
    /models/agg/total/month
    /models/agg/total/year
]

This will build the following tree

models
   |
   |--- stats
   |     |
   |     |--- mean
   |     |--- stdev
   |
   |--- agg
         |
         |--- total
                |
                |--- month
                |--- year

Now to access all of the actors in sub trees we can use wildcards.

Using /models/* will return

[
    /models/stats/mean
    /models/stats/stddev
    /models/agg/total/month
    /models/agg/total/year
]

Using /models/stats/* will return

[
    /models/stats/mean
    /models/stats/stddev
]

Actor References and Actor Selections

Actor References relate to an actor path. When a actor path is resolved, the resolution process returns one or more ActorRef's. Rarely will you interact directly with an ActorRef. When an ActorPath is resolved we get and ActorSelection which is an abstraction over a collection of ActorRefs.

Resolving Actor Paths

To resolve an actor path, we have several operators at our disposal !!, !~ or the named equivalents resolve, resolveLazy. These operators are able to resolve many types to an ActorSelection a few examples are:

let selection1 = resolve "/models/stats/mean"

which gives us

ActorSelection [ActorRef actor://HP20024950_Fsi_8492@*/models/stats/mean]
let selection2 = !!"/models/stats/mean"

which gives us

ActorSelection [ActorRef actor://HP20024950_Fsi_8492@*/models/stats/mean]
let selection3 = !!["/models/agg/total/*"; "/models/stats/mean"]

which gives us

ActorSelection
  [ActorRef actor://HP20024950_Fsi_8492@*/models/agg/total/month;
   ActorRef actor://HP20024950_Fsi_8492@*/models/agg/total/year;
   ActorRef actor://HP20024950_Fsi_8492@*/models/stats/mean]

for a complete list see here.

Actor Selection combinators

The library also provides a set of functions over ActorSelection see here. These all you to take an ActorSelection create a new actor selection. For example if I wanted to exclude selection2 from selection3 I could do the following

let selection4 = ActorSelection.exclude selection2 selection3

which gives us

ActorSelection
  [ActorRef actor://HP20024950_Fsi_8492@*/models/agg/total/month;
   ActorRef actor://HP20024950_Fsi_8492@*/models/agg/total/year]
namespace Cricket
type ActorHost =
  interface IDisposable
  private new : configuration:ActorHostConfiguration -> ActorHost
  member private Configure : f:(ActorHostConfiguration -> ActorHostConfiguration) -> unit
  member private RegisterActor : ref:ActorRef -> unit
  member private ResolveActor : name:ActorPath -> ActorRef list
  member SubscribeEvents : eventF:('a0 -> unit) -> ActorHost
  member private CancelToken : CancellationToken
  member private EventStream : IEventStream
  member private Name : string
  static member Dispose : unit -> unit
  ...

Full name: Cricket.ActorHost
static member ActorHost.Start : ?name:string * ?loggers:ILogWriter list * ?serializer:'a0 * ?registry:ActorRegistry * ?metrics:Diagnostics.MetricsConfiguration * ?tracing:Diagnostics.TracingConfiguration * ?cancellationToken:System.Threading.CancellationToken -> ActorHost
val createActor : localName:string -> ActorRef

Full name: Actor_lookup.createActor
val localName : string
val actor : ActorConfigurationBuilder

Full name: Cricket.ActorConfiguration.actor
custom operation: name (string)

Calls ActorConfigurationBuilder.Name
Multiple items
module Actor

from Cricket

--------------------
type Actor<'a> =
  interface IDisposable
  interface IActor<'a>
  interface IActor
  new : defn:ActorConfiguration<'a> -> Actor<'a>
  override ToString : unit -> string
  member Ref : ActorRef

Full name: Cricket.Actor<_>

--------------------
new : defn:ActorConfiguration<'a> -> Actor<'a>
val spawn : config:ActorConfiguration<'a> -> ActorRef

Full name: Cricket.Actor.spawn
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val iter : action:('T -> unit) -> list:'T list -> unit

Full name: Microsoft.FSharp.Collections.List.iter
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val selection1 : ActorSelection

Full name: Actor_lookup.selection1
val resolve : a:'a -> ActorSelection

Full name: Cricket.ActorOperators.resolve
val selection2 : ActorSelection

Full name: Actor_lookup.selection2
val selection3 : ActorSelection

Full name: Actor_lookup.selection3
val selection4 : ActorSelection

Full name: Actor_lookup.selection4
Multiple items
union case ActorSelection.ActorSelection: ActorRef list -> ActorSelection

--------------------
module ActorSelection

from Cricket

--------------------
type ActorSelection =
  | ActorSelection of ActorRef list
  member private Refs : ActorRef list
  static member op_Implicit : s:'a -> ActorSelection

Full name: Cricket.ActorSelection
val exclude : ActorSelection -> r:ActorSelection -> ActorSelection

Full name: Cricket.ActorSelection.exclude
Fork me on GitHub