use async_trait::async_trait;
use joerl::{Actor, ActorContext, ActorSystem, Message};
use tokio::time::{Duration, sleep};
#[derive(Clone)]
struct Worker {
id: usize,
}
#[async_trait]
impl Actor for Worker {
async fn started(&mut self, ctx: &mut ActorContext) {
println!("[Worker {}] Started with Pid: {}", self.id, ctx.pid());
}
async fn handle_message(&mut self, msg: Message, ctx: &mut ActorContext) {
if let Some(task) = msg.downcast_ref::<String>() {
println!("[Worker {}] Processing task: {}", self.id, task);
sleep(Duration::from_millis(100)).await;
println!("[Worker {}] Task completed: {}", self.id, task);
if let Some(manager_pid) = ctx.whereis("manager") {
let result = format!("Worker {} completed: {}", self.id, task);
ctx.send(manager_pid, Box::new(result)).await.ok();
}
}
}
async fn stopped(&mut self, reason: &joerl::ExitReason, _ctx: &mut ActorContext) {
println!("[Worker {}] Stopped: {}", self.id, reason);
}
}
struct Manager {
tasks_completed: usize,
}
#[async_trait]
impl Actor for Manager {
async fn started(&mut self, ctx: &mut ActorContext) {
println!("[Manager] Started with Pid: {}", ctx.pid());
}
async fn handle_message(&mut self, msg: Message, _ctx: &mut ActorContext) {
if let Some(result) = msg.downcast_ref::<String>() {
self.tasks_completed += 1;
println!("[Manager] Received result: {}", result);
println!("[Manager] Total tasks completed: {}", self.tasks_completed);
}
}
async fn stopped(&mut self, reason: &joerl::ExitReason, _ctx: &mut ActorContext) {
println!(
"[Manager] Stopped: {} (Total tasks: {})",
reason, self.tasks_completed
);
}
}
#[tokio::main]
async fn main() {
println!("=== Named Processes Example ===\n");
let system = ActorSystem::new();
let manager = system.spawn(Manager { tasks_completed: 0 });
system.register("manager", manager.pid()).unwrap();
println!("✓ Registered manager with name 'manager'");
let mut workers = Vec::new();
for i in 1..=3 {
let worker = system.spawn(Worker { id: i });
let name = format!("worker{}", i);
system.register(&name, worker.pid()).unwrap();
println!("✓ Registered {} with name '{}'", worker.pid(), name);
workers.push(worker);
}
println!("\n--- Registered Names ---");
let registered = system.registered();
println!("All registered names: {:?}\n", registered);
println!("--- Sending Tasks ---");
for i in 1..=3 {
let worker_name = format!("worker{}", i);
if let Some(worker_pid) = system.whereis(&worker_name) {
let task = format!("Task-{}", i);
println!("Sending {} to {}", task, worker_name);
system.send(worker_pid, Box::new(task)).await.unwrap();
}
}
sleep(Duration::from_millis(500)).await;
println!("\n--- Name Lookups ---");
if let Some(pid) = system.whereis("manager") {
println!("Manager Pid: {}", pid);
}
if let Some(pid) = system.whereis("worker1") {
println!("Worker1 Pid: {}", pid);
}
println!("\n--- Unregistering ---");
system.unregister("worker3").unwrap();
println!("✓ Unregistered 'worker3'");
match system.whereis("worker3") {
Some(_) => println!("✗ worker3 still registered (unexpected)"),
None => println!("✓ worker3 no longer registered"),
}
println!("\n--- Final Registered Names ---");
let final_registered = system.registered();
println!("Remaining registered names: {:?}", final_registered);
println!("\n--- Direct Manager Communication ---");
if let Some(manager_pid) = system.whereis("manager") {
system
.send(manager_pid, Box::new("Direct message".to_string()))
.await
.unwrap();
}
sleep(Duration::from_millis(200)).await;
println!("\n=== Example Complete ===");
}