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
//! Defines the application callback boundary for runtime events.
//!
//! [`Subscribe`] implementations enter a supervisor through
//! [`SupervisorBuilder::with_subscribers`](crate::SupervisorBuilder::with_subscribers).
//! Each implementation gets its own bounded queue and serial callback lane after runtime startup.
//!
//! Ordinary runtime events pass through the shared bus and the subscriber queue.
//! After a full lane catches up, Taskvisor delivers its coalesced overflow summary directly when
//! the lane remains active.
//! Subscribers are for observation, not runtime state or reliable task results.
use NonZeroUsize;
use crateEvent;
const DEFAULT_QUEUE_CAPACITY: NonZeroUsize = new.unwrap;
/// Callback-worker choice for a subscriber's serial lane.
///
/// This enum is non-exhaustive; include a wildcard arm when matching it.
/// Synchronous observer for best-effort [`Event`] values.
///
/// Each subscriber has one serial lane.
/// By default, all lanes use one fixed shared worker.
/// [`SubscriberExecution::Dedicated`] gives one lane its own worker.
/// Events delivered to [`on_event`](Self::on_event) keep FIFO order for that subscriber.
/// Shutdown or a failed callback lane can still discard queued events.
/// Dedicated lanes may run concurrently with the shared worker and with each other.
/// These callbacks do not use Tokio async workers or its blocking pool.
///
/// Keep shared callbacks short.
/// Dedicated execution isolates a callback that may block, but that lane can still fill its own
/// queue and outlive the shutdown deadline.
/// Copy the needed fields into an application-owned channel when handling requires async I/O.
/// The borrowed event is valid only for the callback.
///
/// A full queue drops the incoming event only for that subscriber.
/// Taskvisor counts dropped ordinary events and delivers one direct
/// [`SubscriberOverflow`](crate::EventKind::SubscriberOverflow) summary after the lane catches up.
/// Dropping an internal diagnostic, or panicking while handling one, does not generate another diagnostic.
///
/// Taskvisor catches an unwinding panic from an ordinary event callback and tries to publish
/// a [`SubscriberPanicked`](crate::EventKind::SubscriberPanicked) event.
/// A `panic = "abort"` build exits instead.
///
/// During shutdown, all subscriber lanes share one drain timeout.
/// Queued events are dropped at the deadline.
/// A callback already running cannot be aborted and may continue on its worker thread after shutdown returns.
/// Taskvisor does not join callback workers or wait for their thread-local destructors.
///
/// # Examples
///
/// ```rust,no_run
/// use std::num::NonZeroUsize;
/// use std::sync::Arc;
/// use taskvisor::{Event, EventKind, Subscribe, Supervisor, SupervisorConfig};
///
/// struct Metrics;
///
/// impl Subscribe for Metrics {
/// fn on_event(&self, event: &Event) {
/// if event.kind == EventKind::AttemptFailed {
/// // Update an in-memory counter.
/// }
/// }
///
/// fn name(&self) -> &str {
/// "metrics"
/// }
///
/// fn queue_capacity(&self) -> NonZeroUsize {
/// NonZeroUsize::new(2048).unwrap()
/// }
/// }
///
/// let subscribers: Vec<Arc<dyn Subscribe>> = vec![Arc::new(Metrics)];
/// let supervisor = Supervisor::builder(SupervisorConfig::default())
/// .with_subscribers(subscribers)
/// .build();
/// // Start it with `Supervisor::run`, `run_until`, or `serve`.
/// ```