Rio

Distributed stateful services inspired by Orleans

This crate provides a framework for scalable, distributed and stateful services based on message passing between objects

Application

Most of your application code will be written in forms of ServiceObjects and Messages

```rust use asynctrait::asynctrait; use rio_rs::prelude::*; use serde::{Deserialize, Serialize}; use std::sync::Arc;

[derive(TypeName, Message, Deserialize, Serialize)]

pub struct HelloMessage { pub name: String }

[derive(TypeName, Message, Deserialize, Serialize)]

pub struct HelloResponse {}

[derive(TypeName, FromId, Default)]

pub struct HelloWorldService { pub id: String, }

[async_trait]

impl Handler for HelloWorldService { type Returns = HelloResponse; async fn handle( &mut self, message: HelloMessage, app_data: Arc, ) -> Result { println!("Hello world"); Ok(HelloResponse {}) } } ```

Running Server

To run your application you need to spin up your servers, the Server

```rust use riors::prelude::*; use riors::cluster::storage::sql::{SqlMembersStorage}; use riors::objectplacement::sql::SqlObjectPlacementProvider;

// Copied from the snippet above

use asynctrait::asynctrait;

use serde::{Deserialize, Serialize};

use std::sync::Arc;

#

#[derive(TypeName, Message, Deserialize, Serialize)]

pub struct HelloMessage {

pub name: String

}

#

#[derive(TypeName, Message, Deserialize, Serialize)]

pub struct HelloResponse {}

#

#[derive(TypeName, FromId, Default)]

pub struct HelloWorldService {

pub id: String,

}

#

#[async_trait]

impl Handler for HelloWorldService{

type Returns = HelloResponse;

async fn handle(

&mut self,

message: HelloMessage,

app_data: Arc,

) -> Result {

println!("Hello world");

Ok(HelloResponse {})

}

}

[tokio::main]

async fn main() { let addr = "0.0.0.0:5000";

// Configure types on the server's registry
let mut registry = Registry::new();
registry.add_static_fn::<HelloWorldService, String, _>(FromId::from_id);
registry.add_handler::<HelloWorldService, HelloMessage>();

// Configure the Cluster Membership provider
let pool = SqlMembersStorage::pool()
    .connect("sqlite::memory:")
    .await
    .expect("Membership database connection failure");
let members_storage = SqlMembersStorage::new(pool);
members_storage.migrate().await;

let membership_provider_config = PeerToPeerClusterConfig::default();
let membership_provider =
    PeerToPeerClusterProvider::new(members_storage, membership_provider_config);

// Configure the object placement
let pool = SqlMembersStorage::pool()
    .connect("sqlite::memory:")
    .await
    .expect("Object placement database connection failure");
let object_placement_provider = SqlObjectPlacementProvider::new(pool);
object_placement_provider.migrate().await;

// Create the server object
let mut server = Server::new(
    addr.to_string(),
    registry,
    membership_provider,
    object_placement_provider,
);

// Run the server
// server.serve().await;

} ```

Client

Communicating with the cluster is just a matter of sending the serialized known messages via TCP. The [client] module provides an easy way of achieving this:

```norun use riors::prelude::*; use rio_rs::cluster::storage::sql::{SqlMembersStorage};

// Copied from the snippet above

use asynctrait::asynctrait;

use serde::{Deserialize, Serialize};

use std::sync::Arc;

#

#[derive(TypeName, Message, Deserialize, Serialize)]

pub struct HelloMessage {

pub name: String

}

#

#[derive(TypeName, Message, Deserialize, Serialize)]

pub struct HelloResponse {}

#

#[derive(TypeName, FromId, Default)]

pub struct HelloWorldService {

pub id: String,

}

#

#[async_trait]

impl Handler for HelloWorldService {

type Returns = HelloResponse;

async fn handle(

&mut self,

message: HelloMessage,

app_data: Arc,

) -> Result {

println!("Hello world");

Ok(HelloResponse {})

}

}

[tokio::main]

async fn main() -> Result<(), Box> { // Member storage configuration (Rendezvous) let pool = SqlMembersStorage::pool() .connect("sqlite::memory:") .await?; let membersstorage = SqlMembersStorage::new(pool); # membersstorage.migrate().await;

// Create the client
let mut client = ClientBuilder::new()
    .members_storage(members_storage)
    .build()?;

let payload = HelloMessage { name: "Client".to_string() };
let response: HelloResponse = client
    .send(
        "HelloWorldService".to_string(),
        "any-string-id".to_string(),
        &payload,
    ).await?;

// response is a `HelloResponse {}`
Ok(())

} ```

Roadmap

There are a few things that must be done before v0.1.0: