Docs Crates.io Build & test Codecov

genserver: generate a server

genserver is tiny async actor framework, inspired by Elixir's GenServer. With few lines code, we do great things.

Check out the docs for more details.

Synopsis

First run:

console $ cargo add genserver

Then try this code here in your crate (note the 2 features which need to be enabled in main.rs or lib.rs for applications and libraries respectively):

```rust // these two features must be enabled at the crate level

![feature(genericassociatedtypes, typealiasimpl_trait)]

use std::future::Future;

use genserver::{make_registry, GenServer};

struct MyServer { // Any state your server needs can go right // in here. We keep a registry around in case // we want to call any other servers from our // server. registry: MyRegistry, }

impl GenServer for MyServer { // Message type for this server. type Message = String; // The type of the registry defined by the make_registry attribute macro. type Registry = MyRegistry; // The response type for calls. type Response = String;

// The call response type, a future, which returns Self::Response.
type CallResponse<'a> = impl Future<Output = Self::Response> + 'a;
// The cast response type, also a future, which returns unit.
type CastResponse<'a> = impl Future<Output = ()> + 'a;

fn new(registry: Self::Registry) -> Self {
    // When are server is started, the registry passes a copy
    // of itself here. We keep it around so we can call
    // other servers from this one.
    Self { registry }
}

// Calls to handle_call will block until our `Response` is returned.
// Because they return a future, we can return an async block here.
fn handle_call(&mut self, message: Self::Message) -> Self::CallResponse<'_> {
    println!("handle_call received {}", message);
    std::future::ready("returned from handle_call".into())
}

// Casts always return (), because they do not block callers and return
// immediately.
fn handle_cast(&mut self, message: Self::Message) -> Self::CastResponse<'_> {
    println!("handle_cast received {}", message);
    std::future::ready(())
}

}

[make_registry{

myserver: MyServer

}] struct MyRegistry;

tokiotest::blockon(async { let registry = MyRegistry::start().await;

let response = registry
    .call_myserver("calling myserver".into())
    .await
    .unwrap();
registry
    .cast_myserver("casting to myserver".into())
    .await
    .unwrap();

}); ```