[][src]Crate herbert

Management for actor services and message routing.

An actor is a long-lived thread that performs a specific function or set of functions and consumes a channel of requests from other threads using protocols to describe how and on what data those functions should be performed.

While the actor model has numerous benefits, exherting control over actors (such as during a shutdown event) and keeping track of all of their channels can be challenging. This module provides facilities that support the use of the actor model by addressing those challenges.

To maintain a registry of actors, keep track of their channels, and respond to control events, a special type of actor called a router is launched. A Router encapsulates the channels through which clients interact with the router and the actors it maintains. The router's registry maps an ID for each actor to an Actor type similar to Router which encapsulates the channels through which actors receive their input.

Actors are spawned through a control message to the router. They are provided an ActorContext that provides the channels over which the function receives its inputs and control messages, and a channel over which it can communicate its status back to the router.

An actor function must:

  • Use the select! macro that is re-exported from crossbeam_channel to receive from both the request channel and the control channel.
  • Convert the Any + Send trait objects it receives over the request channel into the correct concrete type.
  • Respond to ActorCtl::Stop messages it receives over the control channel by promptly stablizing its state, sending the router an ActorStatus::Stopped status message, and exiting.

Simple Example

#[macro_use]
extern crate herbert;
use herbert::prelude::*;

fn main() {
    // Create a router. This is manditory.
    let router = Router::run("example");

    // Spawn an actor, here named "herbert".
    spawn_actor!(router, "herbert", |ctx: ActorContext| {
        loop {
            select! {
                // Normal message channel.
                recv(ctx.req) -> msg => {
                    match msg {
                        Ok(any) => {
                            // Convert trait object into concrete type.
                            if let Some(value) = any.downcast_ref::<String>() {
                                // Do some work.
                                println!("received order: {}", value);
                            } else {
                                // Bad value, here we're just ignoring it.
                            }
                        }
                        Err(e) => {
                            // Error receiving a normal message, choosing to terminate.
                            break;
                        }
                    }
                }
                // Control message channel.
                recv(ctx.ctl) -> msg => {
                    match msg {
                        Ok(ActorCtl::Stop) => {
                            // We have been requested to stop.
                            // Stabilize any state and then break the loop to exit.
                            break;
                        }
                        Err(e) => {
                            // Error receiving a control message, choosing to terminate.
                            break;
                        },
                    }
                }
            }
        }
        // Notify the router we are stopped as our last action.
        ctx.stat.send(ActorStatus::Stopped(ctx.id.clone())).unwrap();
    });

    // Send our order to the "herbert" actor thread.
    send_actor!(router, "herbert", String::from("2 gorditas")).unwrap();

    // ...

    // Shut down the router.
    router.shutdown();
}

Modules

prelude

The things you'll need.

Macros

actor_get_actor

A wrapper for executing a RouterCtl::Get request on a Router, from within another actor.

actor_has_actor

A wrapper for executing a RouterCtl::Has request on a Router, from within another actor.

actor_send_actor

A wrapper for sending a message to an actor through a Router, from within another actor.

actor_spawn_actor

A wrapper for executing a RouterCtl::Spawn request on a Router, from within another actor.

actor_stop_actor

A wrapper for executing a RouterCtl::StopActor request on a Router, from within another actor.

get_actor

A wrapper for executing a RouterCtl::Get request on a Router.

has_actor

A wrapper for executing a RouterCtl::Has request on a Router.

send_actor

A wrapper for sending a message to an actor through a Router.

spawn_actor

A wrapper for executing a RouterCtl::Spawn request on a Router.

stop_actor

A wrapper for executing a RouterCtl::StopActor request on a Router.

Structs

Actor

A handle to an actor.

ActorContext

A handle to communication channels provided to an actor function.

Router

A handle to the actor management thread.

RouterRequest

A request to route a message to an actor.

Enums

ActorCtl

Messages that exhert control over actors.

ActorStatus

Status messages sent from an actor to the supervising router.

RouterCtl

A control message for the router.

Type Definitions

ActorFn

A signature for actor thread functions.

Message

The type signature of the messages that are consumed by actors.