Actors

Actors
Login

The purpose of this package is to allow you to create actors in Go.

An introduction and tutorial to using this library is available.

Think of an actor like a little server: it is created, it receives messages and processes them, and it terminates. As part of processing a message, it can reply to the message, it can send messages to other actors that it knows of, it can create new actors, and it can terminate.

Each actor has a mailbox. Clients of the actor call the actor's public API, which will typically post messages into this mailbox. The actor will see that there are messages in the mailbox, retrieve each message, and process them. Whilst posting a message into a mailbox is mainly an asynchronous activity, the message itself may require a reply. The sender can choose to block and wait for the reply at any time. This functionality is provided by the MsgSync and MsgSyncBase types.

Each actor-server is a Go-routine. The mailbox is implemented by chans. It is safe for multiple concurrent Go-routines to post messages to the same actor, and it is always the case that an actor-server itself is single-threaded - a single Go-routine. If you wish for more elaborate setups then that is for you: some sort of sharding or session management across a set of actors of the same type is perfectly possible, but is not currently provided directly by this package.

Use different struct types to implement the client-side and the server-side of each actor. The client-side should embed (probably anonymously) an implementation of the Client type. The server-side should anonymously embed an implementation of the Server type (either BackPressureServerBase or ServerBase).

The server-side of each actor must satisfy the Server interface, and so has to provide three methods: Init, HandleMsg, and Terminated. BackPressureServerBase and ServerBase have implementations of all of these, so you need only reimplement the ones you need. For all methods that you implement yourself on the server-side, make certain that you also call the embedded version. If you fail to do this for Init, then various parts of the actor will not be set up properly. If you fail to do this for HandleMsg then the actor will not be able to be terminate, and if you fail to do this for Terminated, then termination subscriptions will not function correctly.

Init is the first method invoked by the new actor, and is called synchronously as part of spawning the new actor. I.e. at the point that Init is invoked (in the new actor's Go-routine), Spawn will not have returned, and no one will yet know of the existence of this new actor. So, if the new actor decides to send messages to itself, it can guarantee that those messages will be the first items in its own mailbox. This is useful for being able to do deferred asynchronous initialisation, for example. If Init fails (returns a non-nil error), then Spawn fails too, and returns the same error.

HandleMsg is invoked for each message that is received from the actor's mailbox. HandleMsg returns an error; if the error is non-nil then the actor terminates: the actor's mailbox is closed, Terminated is invoked, and finally the actor's Go-routine exits. All remaining messages in the actor's mailbox are discarded, and anyone else waiting on responses from the actor will be informed that the actor has terminated and no further responses will be forthcoming.

An introduction and tutorial to using this library is available.