handler_pattern/
handler_pattern.rs

1use actor12::{Actor, Call, Handler, Init, MpscChannel, Multi, spawn};
2use futures::future;
3use std::future::Future;
4
5// Actor that can handle multiple different message types using the Handler trait
6pub struct MultiHandlerActor {
7    counter: i32,
8    name: String,
9}
10
11// Different message types
12#[derive(Debug)]
13pub struct IncrementMsg;
14
15#[derive(Debug)]
16pub struct GetCountMsg;
17
18#[derive(Debug)]
19pub struct SetNameMsg(pub String);
20
21#[derive(Debug)]
22pub struct GetNameMsg;
23
24impl Actor for MultiHandlerActor {
25    type Spec = String; // actor name
26    type Message = Multi<Self>;
27    type Channel = MpscChannel<Self::Message>;
28    type Cancel = ();
29    type State = ();
30
31    fn state(_spec: &Self::Spec) -> Self::State {}
32
33    fn init(ctx: Init<'_, Self>) -> impl Future<Output = Result<Self, Self::Cancel>> + Send + 'static {
34        let name = ctx.spec;
35        println!("MultiHandlerActor '{}' initialized", name);
36        future::ready(Ok(MultiHandlerActor {
37            counter: 0,
38            name,
39        }))
40    }
41}
42
43// Implement Handler for each message type
44impl Handler<IncrementMsg> for MultiHandlerActor {
45    type Reply = Result<i32, anyhow::Error>;
46
47    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, _msg: IncrementMsg) -> Self::Reply {
48        self.counter += 1;
49        println!("Actor '{}': Counter incremented to {}", self.name, self.counter);
50        Ok(self.counter)
51    }
52}
53
54impl Handler<GetCountMsg> for MultiHandlerActor {
55    type Reply = Result<i32, anyhow::Error>;
56
57    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, _msg: GetCountMsg) -> Self::Reply {
58        println!("Actor '{}': Current counter is {}", self.name, self.counter);
59        Ok(self.counter)
60    }
61}
62
63impl Handler<SetNameMsg> for MultiHandlerActor {
64    type Reply = Result<String, anyhow::Error>;
65
66    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, msg: SetNameMsg) -> Self::Reply {
67        let old_name = self.name.clone();
68        self.name = msg.0;
69        println!("Actor name changed from '{}' to '{}'", old_name, self.name);
70        Ok(old_name)
71    }
72}
73
74impl Handler<GetNameMsg> for MultiHandlerActor {
75    type Reply = Result<String, anyhow::Error>;
76
77    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, _msg: GetNameMsg) -> Self::Reply {
78        println!("Actor '{}': Returning current name", self.name);
79        Ok(self.name.clone())
80    }
81}
82
83// String handler for dynamic messages
84impl Handler<String> for MultiHandlerActor {
85    type Reply = Result<String, anyhow::Error>;
86
87    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, msg: String) -> Self::Reply {
88        let response = format!("Actor '{}' received string: '{}'", self.name, msg);
89        println!("{}", response);
90        Ok(response)
91    }
92}
93
94#[tokio::main]
95async fn main() -> anyhow::Result<()> {
96    println!("=== Handler Pattern Example ===\n");
97
98    // Spawn the actor
99    let actor = spawn::<MultiHandlerActor>("CounterBot".to_string());
100
101    // Use different message types with the same actor
102    println!("1. Testing typed messages:");
103    
104    // Increment counter
105    let count1: Result<i32, anyhow::Error> = actor.ask_dyn(IncrementMsg).await;
106    println!("Result: {:?}", count1);
107
108    let count2: Result<i32, anyhow::Error> = actor.ask_dyn(IncrementMsg).await;  
109    println!("Result: {:?}", count2);
110
111    // Get current count
112    let current: Result<i32, anyhow::Error> = actor.ask_dyn(GetCountMsg).await;
113    println!("Current count: {:?}", current);
114
115    println!("\n2. Testing name operations:");
116    
117    // Change name
118    let old_name: Result<String, anyhow::Error> = actor.ask_dyn(SetNameMsg("SuperBot".to_string())).await;
119    println!("Previous name: {:?}", old_name);
120
121    // Get current name
122    let name: Result<String, anyhow::Error> = actor.ask_dyn(GetNameMsg).await;
123    println!("Current name: {:?}", name);
124
125    println!("\n3. Testing dynamic string messages:");
126    
127    // Send string messages dynamically
128    let response1: Result<String, anyhow::Error> = actor.ask_dyn("Hello there!".to_string()).await;
129    println!("Response: {:?}", response1);
130
131    let response2: Result<String, anyhow::Error> = actor.ask_dyn("How are you doing?".to_string()).await;
132    println!("Response: {:?}", response2);
133
134    println!("\n4. Final state check:");
135    let final_count: Result<i32, anyhow::Error> = actor.ask_dyn(GetCountMsg).await;
136    let final_name: Result<String, anyhow::Error> = actor.ask_dyn(GetNameMsg).await;
137    println!("Final count: {:?}, Final name: {:?}", final_count, final_name);
138
139    Ok(())
140}