Model & Customization
Riker requires a Model
to set the message type used throughout the system and specify modules that provide core services. Model
is a trait that can be implemented on a Rust type which is then used to create the ActorSystem
.
Model Trait
Let's take a look at the Model
trait:
pub trait Model : Sized { /// The message type used throughout the system. /// `Actor.receive` expects this type type Msg: Message; /// Dispatcher executes actors and futures type Dis: Dispatcher; /// Logger provides global logging, e.g. info!("hello"); type Log: LoggerProps<Msg = Self::Msg>; /// Dead letters subscribes to the dead letters channel type Ded: DeadLetterProps<Msg = Self::Msg>; /// Timer provides message scheduling, e.g. `ctx.schedule_once` type Tmr: TimerFactory<Msg = Self::Msg>; /// Event store provides the storage system for events/messages type Evs: EventStore<Msg=Self::Msg>; type Tcp: IoManagerProps<Msg = Self::Msg>; type Udp: IoManagerProps<Msg = Self::Msg>; }
The Model
trait consists of various trait types that are used to customize a Riker system, including the message type.
Default Model
A default model is provided by the riker-default
crate that uses default Riker modules but still allows you to specify your message type (protocol).
Using the default model:
extern crate riker; extern crate riker_default; use riker::actors::*; use riker_default::DefaultModel; // Get a default model with String as the message type let model: DefaultModel<String> = DefaultModel::new(); let sys = ActorSystem::new(&model).unwrap();
The default model helps get the initial stages of your application started. It's also a good choice for integration tests. When you're ready to use other modules, for example an event store module for a specific database, you can use your own model.
Custom Model
Since Model
is a trait it can be implemented on a simple struct.
Let's look at how we can create a model to change the event store and logging modules:
extern crate riker; extern crate riker_default; use riker::actors::*; use riker_default::*; // <-- we're still going to use some default modules struct MyModel; impl Model for MyModel { type Msg = String; type Dis = ThreadPoolDispatcher; type Ded = DeadLettersActor<Self::Msg>; type Tmr = BasicTimer<Self::Msg>; type Evs = Redis<Self::Msg>; // <-- a module to provide Redis storage type Tcp = TcpManager<Self::Msg>; type Udp = TcpManager<Self::Msg>; type Log = MyLogger<Self::Msg>; // <-- our own Log module } let sys = ActorSystem::new(&MyModel).unwrap();