pub trait AbstractProcess: Sized
where Self::Serializer: CanSerialize<Self::Arg> + CanSerialize<Result<(), StartupError<Self>>> + CanSerialize<ShutdownMessage<Self::Serializer>> + CanSerialize<()> + CanSerialize<(Process<Result<(), StartupError<Self>>, Self::Serializer>, Tag, Self::Arg)> + CanSerialize<ProtocolCapture<(Process<Result<(), StartupError<Self>>, Self::Serializer>, Tag, Self::Arg)>>,
{ type State; type Serializer; type Arg; type Handlers: Handlers<Self>; type StartupError: Debug; // Required method fn init( config: Config<Self>, arg: Self::Arg ) -> Result<Self::State, Self::StartupError>; // Provided methods fn terminate(_state: Self::State) { ... } fn handle_link_death(_state: State<'_, Self>, _tag: Tag) { ... } fn start(arg: Self::Arg) -> Result<ProcessRef<Self>, StartupError<Self>> { ... } fn start_as<N: ProcessName>( name: &N, arg: Self::Arg ) -> Result<ProcessRef<Self>, StartupError<Self>> { ... } fn link() -> AbstractProcessBuilder<'static, Self> { ... } fn link_with(tag: Tag) -> AbstractProcessBuilder<'static, Self> { ... } fn configure(config: &ProcessConfig) -> AbstractProcessBuilder<'_, Self> { ... } fn on_node(node: u64) -> AbstractProcessBuilder<'static, Self> { ... } }
Expand description

Building block for processes that act as a server of a client-server relation.

An AbstractProcess is like any other process in lunatic, it can hold state, receive messages and so on. Their main advantage is that they provide a type-safe interface for dealing with requests.

Startup

AbstractProcesses can be started using the Self::start function, or Self::start_as for a named process. Calls to these functions will block until the process is started and the Self::init function finishes. A custom return error can be specified using the Self::StartupError type. If the init function panics, the start functions will return a StartupError::InitPanicked error.

Handlers

Handlers are used to define the types of messages that can be handled by abstract processes. Handlers are defined using the traits MessageHandler, RequestHandler and DeferredRequestHandler.

MessageHandler are used to handle asynchronous messages sent to the abstract process. This means that the sender doesn’t wait for an answer.

The following example shows a Counter abstract process that is able to handle Increment messages. During the handling of a message the handler has access to the internal state of the abstract process.

#[derive(serde::Serialize, serde::Deserialize)]
struct Increment;
impl MessageHandler<Increment> for Counter {
    fn handle(mut state: State<Self>, _: Increment) {
        state.0 += 1;
    }
}

RequestHandler and DeferredRequestHandler expect a return value and the requests are made synchronous, this means that the sender waits for a response.

#[derive(serde::Serialize, serde::Deserialize)]
struct Count;
impl RequestHandler<Count> for Counter {
    type Response = u32;
    fn handle(state: State<Self>, _: Count) -> Self::Response {
        state.0
    }
}

In case of a DeferredRequestHandler, the response doesn’t need to be immediate and can be even delegated to a 3rd process.

impl DeferredRequestHandler<Count> for Counter {
    type Response = u32;
    fn handle(_: State<Self>, _: String, dr: DeferredResponse<Self::Response, Self>) {
        dr.send_response(u32);
    }
}

It is not enough just to define the handlers, they also need to be associated with the AbstractProcess using the Self::Handlers type:

type Handlers = (Message<Increment>, Request<Count>, DeferredRequest<Count>);

Shutdown

An abstract process can be shut down using the ProcessRef::shutdown call. This function will block, until the Self::terminate function finishes.

Required Associated Types§

source

type State

The state of the process.

This value is usually set to Self.

source

type Serializer

The serializer used for all messages sent to and responses sent from the abstract process.

source

type Arg

The argument received by the init function.

This argument is sent from the parent to the child and needs to be serializable by Self::Serializer.

source

type Handlers: Handlers<Self>

Handlers for incoming messages, requests and deferred requests.

They are defined as a tuple and wrapped into Message, Request and DeferredRequest wrappers.

type Handlers = (Message<Handler1>, Message<Handler2>, Request<Handler3>);

Even if there is only one handler, it needs to be defined as a tuple.

type Handlers = (Message<Handler1>,);
source

type StartupError: Debug

Errors that can be returned from the init call to the spawner.

Required Methods§

source

fn init( config: Config<Self>, arg: Self::Arg ) -> Result<Self::State, Self::StartupError>

Entry function of the new process.

This function is executed inside the new process. It will receive the arguments passed to the start or start_as function by the parent. And will return the starting state of the newly spawned process.

The parent will block on the call of start or start_as until this function finishes. This allows startups to be synchronized.

Provided Methods§

source

fn terminate(_state: Self::State)

Called when a shutdown command is received.

This function will be called if another linked process dies.

source

fn start(arg: Self::Arg) -> Result<ProcessRef<Self>, StartupError<Self>>

Starts a new AbstractProcess and returns a reference to it.

This call will block until the init function finishes. If the init function returns an error, it will be returned as StartupError::Custom(error). If the init function panics during execution, it will return StartupError::InitPanicked.

source

fn start_as<N: ProcessName>( name: &N, arg: Self::Arg ) -> Result<ProcessRef<Self>, StartupError<Self>>

Starts the process and registers it under name. If another process is already registered under the same name, it will return a Err(StartupError::NameAlreadyRegistered(proc)) with a reference to the existing process.

This call will block until the init function finishes. If the init function returns an error, it will be returned as StartupError::Custom(error). If the init function panics during execution, it will return StartupError::InitPanicked.

If used in combination with the on_node option, the name registration will be performed on the local node and not the remote one.

Links the to be spawned process to the parent.

Links the to be spawned process to the parent with a specific Tag.

source

fn configure(config: &ProcessConfig) -> AbstractProcessBuilder<'_, Self>

Allows for spawning the process with a specific configuration.

source

fn on_node(node: u64) -> AbstractProcessBuilder<'static, Self>

Sets the node on which the process will be spawned.

Object Safety§

This trait is not object safe.

Implementors§