Crates.io | xan-actor |
lib.rs | xan-actor |
version | |
source | src |
created_at | 2023-09-30 13:44:55.282393+00 |
updated_at | 2025-03-07 01:41:03.727216+00 |
description | Akka actor |
homepage | |
repository | https://github.com/Xanthorrhizol/actor |
max_upload_size | |
id | 988643 |
Cargo.toml error: | TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
$ cargo add xan-actor
$ cargo add serde --features=derive
use xan_actor::ActorSystem;
...
let mut actor_system = ActorSystem::new();
:bulb: The actor doesn't have to use same message type. Single ActorSystem supports it.
use crate::xan_actor::{Actor, Handler, Message, ActorError};
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum MyMessage1 {
A(String),
C(String),
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum MyMessage2 {
B(String),
}
#[derive(thiserror::Error, Debug)]
enum MyError {
#[error("bye")]
Exit,
#[error(transparent)]
ActorError(#[from] ActorError),
}
struct MyActor1 {
pub address: String,
}
struct MyActor2 {
pub address: String,
}
#[async_trait::async_trait]
impl Actor<MyMessage1, MyMessage1, MyError> for MyActor1 {
fn address(&self) -> &str {
&self.address
}
async fn actor(&mut self, msg: MyMessage1) -> Result<MyMessage1, MyError> {
println!("[{}] got MyMessage1: {:?}", self.address(), msg);
Ok(msg)
}
}
#[async_trait::async_trait]
impl Actor<MyMessage2, MyMessage2, MyError> for MyActor2 {
fn address(&self) -> &str {
&self.address
}
async fn actor(&mut self, msg: MyMessage2) -> Result<MyMessage2, MyError> {
println!("[{}] got MyMessage2: {:?}", self.address(), msg);
Ok(msg)
}
}
let actor1 = MyActor1 {
address: "/some/address/1/1".to_string(),
};
actor1.register(&mut actor_system).await;
let actor2 = MyActor2 {
address: "/some/address/2".to_string(),
};
actor2.register(&mut actor_system).await;
let actor3 = MyActor1 {
address: "/some/address/1/2".to_string(),
};
actor3.register(&mut actor_system).await;
// you can send message to multiple actor at once using address with regex
let _ = actor_system.send_broadcast(
"/some/address/1/*".to_string(), /* address as regex */
MyMessage1::A("a1".to_string()), /* message */
).await;
let result = actor_system.send_and_recv::<MyMessage2, MyMessage2>(
"/some/address/2".to_string(), /* address */
MyMessage2::B("b1".to_string()), /* message */
).await;
// restart actors
actor_system.restart(
"/some/address/1/*".to_string(), /* address as regex */
);
// it needs some time. TODO: handle it inside of restart function
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
let result = actor_system.send_and_recv::<MyMessage2, MyMessage2>(
"/some/address/2".to_string(), /* address */
MyMessage2::B("b2".to_string()), /* message */
).await;
// kill and unregister actor
actor_system.unregister(
"*".to_string(), /* address */
);
use xan_actor::JobSpec;
...
let job = JobSpec::new(
Some(2), /* max_iter */
Some(std::time::Duration::from_secs(3)), /* interval */
std::time::SystemTime::now(), /* start_at */
);
if let Ok(Some(recv_rx)) = actor_system.run_job::<MyMessage1, MyMessage1>(
"/some/address/1".to_string(), /* address */
true, /* whether subscribe the handler result or not(true => Some(rx)) */
job, /* job as JobSpec */
MyMessage1::C("c".to_string()), /* message */
).await {
while let Some(result) = recv_rx.recv().await {
println!("result returned");
}
}