Skip to content

Commit b57f19f

Browse files
committed
fix(event): prevent silent WriteEvent loss when EventPlane is dropped
spawn_background_loops previously discarded the EventPlane handle returned by EventPlane::spawn. Dropping that handle aborts every consumer task, turning the per-core event ring buffers into one-way drains — the Data Plane keeps emitting WriteEvents but nothing reads them, so all triggers, CDC streams, and cron dispatches silently stop firing. The function now returns the EventPlane handle tagged #[must_use], and main.rs binds it for the duration of the server's lifetime. EventProducer::push also gains exhaustive BridgeError matching: the new Disconnected arm logs a single warning (latched via AtomicBool) and returns false rather than repeating the warning on every subsequent push or falling through to the catch-all branch.
1 parent 9e41382 commit b57f19f

1 file changed

Lines changed: 28 additions & 1 deletion

File tree

nodedb/src/event/bus.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
//! ```
1515
1616
use std::sync::Arc;
17+
use std::sync::atomic::{AtomicBool, Ordering};
1718

1819
use nodedb_bridge::backpressure::{BackpressureConfig, BackpressureController, PressureState};
1920
use nodedb_bridge::buffer::{Consumer, Producer, RingBuffer};
21+
use nodedb_bridge::error::BridgeError;
2022

2123
use super::types::WriteEvent;
2224

@@ -30,6 +32,10 @@ pub struct EventProducer {
3032
inner: Producer<WriteEvent>,
3133
core_id: usize,
3234
backpressure: Arc<BackpressureController>,
35+
/// Latched once the consumer half is dropped, so we log the
36+
/// disconnect exactly once per producer instead of spamming
37+
/// a warning for every dropped event.
38+
disconnect_logged: AtomicBool,
3339
}
3440

3541
impl EventProducer {
@@ -74,14 +80,34 @@ impl EventProducer {
7480

7581
match self.inner.try_push(event) {
7682
Ok(()) => true,
77-
Err(_) => {
83+
Err(BridgeError::Full { .. }) => {
7884
tracing::warn!(
7985
core = self.core_id,
8086
utilization = util,
8187
"event bus full — event dropped (WAL-backed, will replay on gap)"
8288
);
8389
false
8490
}
91+
Err(BridgeError::Disconnected { .. }) => {
92+
// Consumer dropped — Event Plane is gone (shutdown or lifecycle bug).
93+
// Log once per producer; further events would just be noise.
94+
if !self.disconnect_logged.swap(true, Ordering::Relaxed) {
95+
tracing::warn!(
96+
core = self.core_id,
97+
"event bus consumer disconnected — Event Plane is not running; \
98+
events will be silently dropped on this core until restart"
99+
);
100+
}
101+
false
102+
}
103+
Err(e) => {
104+
tracing::warn!(
105+
core = self.core_id,
106+
error = %e,
107+
"event bus push failed — event dropped"
108+
);
109+
false
110+
}
85111
}
86112
}
87113

@@ -147,6 +173,7 @@ pub fn create_event_bus_with_capacity(
147173
inner: producer,
148174
core_id,
149175
backpressure: Arc::clone(&backpressure),
176+
disconnect_logged: AtomicBool::new(false),
150177
});
151178

152179
consumers.push(EventConsumerRx {

0 commit comments

Comments
 (0)