1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
//! Event handler traits.
//!
//! Rust implementation of `ClusterShell.Event`.
use std::any::Any;
/// Trait for handling worker lifecycle events.
///
/// Implement any subset of these methods to react to events
/// from workers and tasks. All methods have default no-op implementations.
pub trait EventHandler: Send + Sync {
/// Called to indicate that a worker has just started.
fn ev_start(&mut self, _worker: &dyn Any) {}
/// Called for each node to indicate that a worker command for a
/// specific node (or key) has just started.
fn ev_pickup(&mut self, _worker: &dyn Any, _node: &str) {}
/// Called to indicate that a worker has data to read from a specific
/// node (or key).
fn ev_read(&mut self, _worker: &dyn Any, _node: &str, _sname: &str, _msg: &str) {}
/// Called to indicate that a worker has error to read on stderr from
/// a specific node (or key).
///
/// DEPRECATED: use ev_read instead and check if sname is 'stderr'
fn ev_error(&mut self, _worker: &dyn Any) {}
/// Called to indicate that some writing has been done by the worker to a
/// node on a given stream.
fn ev_written(&mut self, _worker: &dyn Any, _node: &str, _sname: &str, _size: usize) {}
/// Called for each node to indicate that a worker command for a specific
/// node has just finished.
fn ev_hup(&mut self, _worker: &dyn Any, _node: &str, _rc: i32) {}
/// Called to indicate that a worker has just finished.
fn ev_close(&mut self, _worker: &dyn Any, _timedout: bool) {}
/// Routing event (private). Called to indicate that a (meta)worker has just
/// updated one of its route path.
fn _ev_routing(&mut self, _worker: &dyn Any, _arg: &str) {}
/// Called to indicate that a message has been received on an EnginePort.
fn ev_msg(&mut self, _port: u16, _msg: &str) {}
/// Called to indicate that a timer is firing.
fn ev_timer(&mut self, _timer: &dyn Any) {}
}
#[cfg(test)]
mod tests {
use super::*;
/// Test that default implementations are callable for all methods
#[test]
fn test_default_impls_callable() {
struct DefaultHandler;
impl EventHandler for DefaultHandler {}
let mut handler = DefaultHandler;
// These should not panic - testing default no-op impls
handler.ev_start(&dyn_any_placeholder());
handler.ev_pickup(&dyn_any_placeholder(), "node1");
handler.ev_read(&dyn_any_placeholder(), "node1", "stdout", "hello");
handler.ev_error(&dyn_any_placeholder());
handler.ev_written(&dyn_any_placeholder(), "node1", "stdout", 100);
handler.ev_hup(&dyn_any_placeholder(), "node1", 0);
handler.ev_close(&dyn_any_placeholder(), false);
handler._ev_routing(&dyn_any_placeholder(), "route_data");
handler.ev_msg(8080, "message");
handler.ev_timer(&dyn_any_placeholder());
}
/// Test that custom implementations can override specific methods
#[test]
fn test_custom_overrides() {
struct CustomHandler {
pub start_count: usize,
pub close_count: usize,
}
impl CustomHandler {
fn new() -> Self {
Self {
start_count: 0,
close_count: 0,
}
}
}
impl EventHandler for CustomHandler {
fn ev_start(&mut self, _worker: &dyn Any) {
self.start_count += 1;
}
fn ev_close(&mut self, _worker: &dyn Any, timedout: bool) {
self.close_count += 1;
assert!(!timedout, "Expected no timeout in this test");
}
}
let mut handler = CustomHandler::new();
handler.ev_start(&dyn_any_placeholder());
handler.ev_start(&dyn_any_placeholder());
handler.ev_close(&dyn_any_placeholder(), false);
assert_eq!(handler.start_count, 2, "ev_start should be called twice");
assert_eq!(handler.close_count, 1, "ev_close should be called once");
}
/// Test that the trait is object-safe and can be used as Box<dyn EventHandler>
///
/// This test verifies that EventHandler is object-safe by:
/// 1. Creating Box<dyn EventHandler> from a concrete type
/// 2. Calling methods through the trait object
/// 3. Storing multiple handlers in a Vec<dyn EventHandler>
#[test]
fn test_object_safety() {
struct Handler1 {
pub count: usize,
}
impl EventHandler for Handler1 {
fn ev_start(&mut self, _worker: &dyn Any) {
self.count += 1;
}
}
struct Handler2 {
pub messages: Vec<String>,
}
impl EventHandler for Handler2 {
fn ev_read(&mut self, _worker: &dyn Any, node: &str, sname: &str, msg: &str) {
self.messages.push(format!("{}:{}:{}", node, sname, msg));
}
}
// This demonstrates object safety - we can store different handler types
// in a Vec of trait objects
let mut handlers: Vec<Box<dyn EventHandler>> = Vec::new();
handlers.push(Box::new(Handler1 { count: 0 }));
handlers.push(Box::new(Handler2 {
messages: Vec::new(),
}));
// Call ev_start on all handlers
for handler in &mut handlers {
handler.ev_start(&dyn_any_placeholder());
}
// Call ev_read on all handlers
for handler in &mut handlers {
handler.ev_read(&dyn_any_placeholder(), "node1", "stdout", "test");
}
// The fact that we can compile and run this code proves that
// EventHandler is object-safe. The trait object can be used
// polymorphically.
assert!(
true,
"Object safety test passed - Box<dyn EventHandler> works"
);
}
/// Helper to create a placeholder for dyn Any
fn dyn_any_placeholder() -> Box<dyn Any> {
Box::new(())
}
/// Test that EventHandler is Send and Sync (required for Box<dyn EventHandler>)
#[test]
fn test_send_sync() {
struct SendSyncHandler;
impl EventHandler for SendSyncHandler {}
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<Box<dyn EventHandler>>();
assert_sync::<Box<dyn EventHandler>>();
assert_send::<SendSyncHandler>();
assert_sync::<SendSyncHandler>();
}
}