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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
//! Lifecycle and restart types for actor supervision.
//!
//! This module defines the types that control how actors are supervised:
//!
//! - [`TerminationReason`] — why an actor stopped (clean shutdown, panic, restart limit)
//! - [`RestartPolicy`] — whether and when to restart (Temporary, Transient, Permanent)
//! - [`RestartConfig`] — full restart specification with limits, rolling window, and backoff
//! - [`ActorFactory`] — creates new actor instances on restart
//!
//! # Restart policies (OTP-inspired)
//!
//! | Policy | Restart on panic? | Restart on clean stop? |
//! |--------|-------------------|------------------------|
//! | `Temporary` | No | No |
//! | `Transient` | Yes | No |
//! | `Permanent` | Yes | Yes |
//!
//! # Backoff
//!
//! When an actor crashes repeatedly, [`BackoffConfig`] applies exponential
//! backoff between restarts to avoid tight crash loops. The delay starts at
//! `initial` and doubles (by `multiplier`) up to `max`.
use Duration;
use mpsc;
use crate;
// =============================================================================
// LIFECYCLE & RESTART TYPES
// =============================================================================
/// Why an actor terminated — used by watches and restart policies.
///
/// # Examples
///
/// ```rust,ignore
/// impl Actor for Supervisor {
/// type State = SupervisorState;
///
/// fn on_actor_terminated(&mut self, state: &mut SupervisorState, event: &ActorTerminated) {
/// match &event.reason {
/// TerminationReason::Stopped => println!("{} stopped cleanly", event.label),
/// TerminationReason::Panicked(msg) => println!("{} panicked: {msg}", event.label),
/// TerminationReason::RestartLimitExceeded => println!("{} gave up", event.label),
/// }
/// }
/// }
/// ```
/// Notification delivered to watchers when a watched actor terminates.
///
/// # Examples
///
/// ```rust,ignore
/// fn on_actor_terminated(&mut self, state: &mut MyState, event: &ActorTerminated) {
/// match event.tag.as_deref() {
/// Some("writer") => state.writer_down = true,
/// Some("reader") => state.reader_down = true,
/// _ => {}
/// }
/// tracing::warn!("Watched actor {} terminated: {:?}", event.label, event.reason);
/// }
/// ```
/// Restart strategy for an actor — mirrors Erlang/OTP child spec strategies.
///
/// # Examples
///
/// ```rust,ignore
/// use murmer::{RestartConfig, RestartPolicy};
///
/// // Restart on crash only (most common for workers)
/// let config = RestartConfig { policy: RestartPolicy::Transient, ..Default::default() };
///
/// // Always restart (for essential services)
/// let config = RestartConfig { policy: RestartPolicy::Permanent, ..Default::default() };
///
/// // Never restart (for one-shot tasks)
/// let config = RestartConfig { policy: RestartPolicy::Temporary, ..Default::default() };
/// ```
/// Configuration for restart limits and backoff behavior.
///
/// # Examples
///
/// ```rust,ignore
/// use murmer::{RestartConfig, RestartPolicy, BackoffConfig};
/// use std::time::Duration;
///
/// let config = RestartConfig {
/// policy: RestartPolicy::Transient, // restart on panic only
/// max_restarts: 3, // max 3 restarts...
/// window: Duration::from_secs(30), // ...within 30 seconds
/// backoff: BackoffConfig {
/// initial: Duration::from_millis(200),
/// max: Duration::from_secs(10),
/// multiplier: 2.0,
/// },
/// };
///
/// let endpoint = system.start_with_config("worker/0", MyFactory, config);
/// ```
/// Exponential backoff configuration for actor restarts.
///
/// # Examples
///
/// ```rust,ignore
/// use murmer::BackoffConfig;
/// use std::time::Duration;
///
/// let backoff = BackoffConfig {
/// initial: Duration::from_millis(500), // first retry after 500ms
/// max: Duration::from_secs(30), // cap at 30s
/// multiplier: 2.0, // 500ms → 1s → 2s → 4s → ...
/// };
/// ```
/// Factory for creating actor instances on restart.
///
/// `&mut self` allows stateful factories (e.g. incrementing restart counters,
/// loading config from disk).
///
/// # Examples
///
/// ```rust,ignore
/// struct CounterFactory { initial_count: i64 }
///
/// impl ActorFactory for CounterFactory {
/// type Actor = Counter;
/// fn create(&mut self) -> (Counter, CounterState) {
/// (Counter, CounterState { count: self.initial_count })
/// }
/// }
///
/// let ep = system.start_with_policy(
/// "counter/0",
/// CounterFactory { initial_count: 0 },
/// RestartPolicy::Permanent,
/// );
/// ```
/// Internal: signals delivered to actors from the system.
pub
/// Internal: a watch entry stored in the receptionist.
pub