use anyhow::Result;
use futures::stream::StreamExt;
use rsactor::{message_handlers, Actor, ActorRef, ActorWeak};
use tokio::time::{interval, Duration};
use tokio_stream::wrappers::IntervalStream;
use tracing::info;
struct Increment; struct Decrement;
#[derive(Debug, Clone, Copy)]
enum Tick {
Fast, Slow, }
struct MyActor {
count: u32, start_up: std::time::Instant, }
impl Actor for MyActor {
type Args = u32; type Error = anyhow::Error;
type IdleEvent = Tick;
async fn on_start(
initial: Self::Args,
actor_ref: &ActorRef<Self>,
) -> Result<Self, Self::Error> {
info!("MyActor started. Initial count: {}.", initial);
actor_ref.subscribe_idle(
IntervalStream::new(interval(Duration::from_millis(300))).map(|_| Tick::Fast),
)?;
actor_ref.subscribe_idle(
IntervalStream::new(interval(Duration::from_secs(1))).map(|_| Tick::Slow),
)?;
Ok(MyActor {
count: initial,
start_up: std::time::Instant::now(),
})
}
async fn on_idle(&mut self, event: Tick, _: &ActorWeak<Self>) -> Result<(), Self::Error> {
match event {
Tick::Fast => println!("300ms tick. Elapsed: {:?}", self.start_up.elapsed()),
Tick::Slow => println!("1s tick. Elapsed: {:?}", self.start_up.elapsed()),
}
Ok(())
}
}
struct DummyMessage;
#[message_handlers]
impl MyActor {
#[handler]
async fn handle_increment(&mut self, _msg: Increment, _: &ActorRef<Self>) -> u32 {
self.count += 1;
println!("MyActor handled Increment. Count is now {}.", self.count);
self.count
}
#[handler]
async fn handle_decrement(&mut self, _msg: Decrement, _: &ActorRef<Self>) -> u32 {
self.count -= 1;
println!("MyActor handled Decrement. Count is now {}.", self.count);
self.count
}
#[handler]
async fn handle_dummy_message(&mut self, _msg: DummyMessage, _: &ActorRef<Self>) -> u32 {
println!("MyActor handled DummyMessage. Count is now {}.", self.count);
self.count
}
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.with_target(false)
.init();
println!("Spawning MyActor...");
let (actor_ref, join_handle) =
rsactor::spawn_with_options::<MyActor>(100, rsactor::SpawnOptions::new().with_idle());
tokio::time::sleep(Duration::from_millis(700)).await;
println!("Sending Increment message...");
let count_after_inc: u32 = actor_ref.ask(Increment).await?;
println!("Reply after Increment: {count_after_inc}");
println!("Sending Decrement message...");
let count_after_dec: u32 = actor_ref.ask(Decrement).await?;
println!("Reply after Decrement: {count_after_dec}");
println!("Sending Increment message again...");
let count_after_inc_2: u32 = actor_ref.ask(Increment).await?;
println!("Reply after Increment again: {count_after_inc_2}");
tokio::time::sleep(Duration::from_millis(700)).await;
println!("Sending StopGracefully message to actor.",);
actor_ref.stop().await;
println!("Waiting for actor to stop...");
let result = join_handle.await?;
match result {
rsactor::ActorResult::Completed { actor, killed } => {
println!(
"Actor stopped. Final count: {}. Killed: {}",
actor.count, killed
);
}
rsactor::ActorResult::Failed {
actor,
error,
phase,
killed,
..
} => {
println!(
"Actor stop failed: {}. Phase: {}, Killed: {}. Final count: {}",
error,
phase,
killed,
actor.as_ref().map(|a| a.count).unwrap_or(0)
);
}
}
println!("Main function finished.");
Ok(())
}