rapace-cell 0.3.0

High-level cell runtime for rapace that eliminates boilerplate
Documentation

High-level cell runtime for rapace

This crate provides boilerplate-free APIs for building rapace cells that communicate via SHM transport. It handles all the common setup that every cell needs:

  • CLI argument parsing (--shm-path or positional args)
  • Waiting for the host to create the SHM file
  • SHM session setup with standard configuration
  • RPC session creation with correct channel ID conventions
  • Service dispatcher setup

Single-service cells

For simple cells that expose a single service:

use rapace_cell::{run, ServiceDispatch};
use rapace::{Frame, RpcError};
use std::future::Future;
use std::pin::Pin;

# struct MyServiceServer;
# impl MyServiceServer {
#     fn new(impl_: ()) -> Self { Self }
#     async fn dispatch_impl(&self, method_id: u32, payload: &[u8]) -> Result<Frame, RpcError> {
#         unimplemented!()
#     }
# }
# impl ServiceDispatch for MyServiceServer {
#     fn dispatch(&self, method_id: u32, payload: &[u8]) -> Pin<Box<dyn Future<Output = Result<Frame, RpcError>> + Send + 'static>> {
#         Box::pin(Self::dispatch_impl(self, method_id, payload))
#     }
# }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let server = MyServiceServer::new(());
    run(server).await?;
    Ok(())
}

Multi-service cells

For cells that expose multiple services:

use rapace_cell::{run_multi, DispatcherBuilder, ServiceDispatch};
use rapace::{Frame, RpcError};
use std::future::Future;
use std::pin::Pin;

# struct MyServiceServer;
# struct AnotherServiceServer;
# impl MyServiceServer {
#     fn new(impl_: ()) -> Self { Self }
#     async fn dispatch_impl(&self, method_id: u32, payload: &[u8]) -> Result<Frame, RpcError> {
#         unimplemented!()
#     }
# }
# impl AnotherServiceServer {
#     fn new(impl_: ()) -> Self { Self }
#     async fn dispatch_impl(&self, method_id: u32, payload: &[u8]) -> Result<Frame, RpcError> {
#         unimplemented!()
#     }
# }
# impl ServiceDispatch for MyServiceServer {
#     fn dispatch(&self, method_id: u32, payload: &[u8]) -> Pin<Box<dyn Future<Output = Result<Frame, RpcError>> + Send + 'static>> {
#         Box::pin(Self::dispatch_impl(self, method_id, payload))
#     }
# }
# impl ServiceDispatch for AnotherServiceServer {
#     fn dispatch(&self, method_id: u32, payload: &[u8]) -> Pin<Box<dyn Future<Output = Result<Frame, RpcError>> + Send + 'static>> {
#         Box::pin(Self::dispatch_impl(self, method_id, payload))
#     }
# }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    run_multi(|builder| {
        builder
            .add_service(MyServiceServer::new(()))
            .add_service(AnotherServiceServer::new(()))
    }).await?;
    Ok(())
}

Configuration

By default, the cell uses a standard SHM configuration that should match most hosts:

  • ring_capacity: 256 descriptors
  • slot_size: 64KB
  • slot_count: 128 slots (8MB total)

The cell always uses even channel IDs starting from 2 (following rapace convention where cells use even IDs and hosts use odd IDs).