dashboard events: unified coord channel + /dashboard/{stream,history}; broker forwards
This commit is contained in:
parent
d48cee7c2d
commit
a478792914
6 changed files with 205 additions and 66 deletions
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
|
|
@ -47,18 +46,21 @@ const EVENT_CHANNEL: usize = 256;
|
|||
/// self-documenting.
|
||||
pub type DueReminder = (String, i64, String, Option<String>);
|
||||
|
||||
/// Intra-process broker event. `recv_blocking` listens on the same
|
||||
/// channel as the dashboard forwarder; the forwarder re-emits each
|
||||
/// event as a `DashboardEvent` with a freshly-stamped seq from the
|
||||
/// Coordinator. The broker itself doesn't stamp seqs — that's a wire
|
||||
/// concern, not a storage concern.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "snake_case", tag = "kind")]
|
||||
pub enum MessageEvent {
|
||||
Sent {
|
||||
seq: u64,
|
||||
from: String,
|
||||
to: String,
|
||||
body: String,
|
||||
at: i64,
|
||||
},
|
||||
Delivered {
|
||||
seq: u64,
|
||||
from: String,
|
||||
to: String,
|
||||
body: String,
|
||||
|
|
@ -69,13 +71,6 @@ pub enum MessageEvent {
|
|||
pub struct Broker {
|
||||
conn: Mutex<Connection>,
|
||||
events: broadcast::Sender<MessageEvent>,
|
||||
/// Monotonic per-process counter stamped onto every emitted
|
||||
/// `MessageEvent`. Persisted nowhere — clients always treat a hive-c0re
|
||||
/// restart as "everything is new" (fresh snapshot, fresh stream of
|
||||
/// seqs starting at 1). Historical rows replayed via `recent_all`
|
||||
/// carry `seq = 0` since they predate the live stream the seq is
|
||||
/// meant to dedupe against.
|
||||
event_seq: AtomicU64,
|
||||
}
|
||||
|
||||
impl Broker {
|
||||
|
|
@ -91,7 +86,6 @@ impl Broker {
|
|||
Ok(Self {
|
||||
conn: Mutex::new(conn),
|
||||
events,
|
||||
event_seq: AtomicU64::new(0),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -99,20 +93,6 @@ impl Broker {
|
|||
self.events.subscribe()
|
||||
}
|
||||
|
||||
/// Current high-water seq. Snapshot endpoints read this *before*
|
||||
/// gathering state so the resulting (snapshot.seq, snapshot) pair
|
||||
/// satisfies: any live event with seq > snapshot.seq is post-snapshot
|
||||
/// (not yet reflected); any with seq <= snapshot.seq either pre-dates
|
||||
/// the snapshot or was already captured by it. Clients dedupe their
|
||||
/// buffered SSE traffic against this value.
|
||||
pub fn current_seq(&self) -> u64 {
|
||||
self.event_seq.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
fn next_seq(&self) -> u64 {
|
||||
self.event_seq.fetch_add(1, Ordering::SeqCst) + 1
|
||||
}
|
||||
|
||||
pub fn send(&self, message: &Message) -> Result<()> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
conn.execute(
|
||||
|
|
@ -121,7 +101,6 @@ impl Broker {
|
|||
)?;
|
||||
drop(conn);
|
||||
let _ = self.events.send(MessageEvent::Sent {
|
||||
seq: self.next_seq(),
|
||||
from: message.from.clone(),
|
||||
to: message.to.clone(),
|
||||
body: message.body.clone(),
|
||||
|
|
@ -175,11 +154,6 @@ impl Broker {
|
|||
)?;
|
||||
let rows = stmt.query_map(params![limit_i], |row| {
|
||||
Ok(MessageEvent::Sent {
|
||||
// Historical events: seq=0 (never compared against live
|
||||
// seqs). Live dedupe windows close against
|
||||
// history_seq = broker.current_seq() captured at fetch
|
||||
// time, not against per-row seqs.
|
||||
seq: 0,
|
||||
from: row.get(0)?,
|
||||
to: row.get(1)?,
|
||||
body: row.get(2)?,
|
||||
|
|
@ -287,7 +261,6 @@ impl Broker {
|
|||
)?;
|
||||
drop(conn);
|
||||
let _ = self.events.send(MessageEvent::Delivered {
|
||||
seq: self.next_seq(),
|
||||
from: from.clone(),
|
||||
to: to.clone(),
|
||||
body: body.clone(),
|
||||
|
|
@ -364,7 +337,6 @@ impl Broker {
|
|||
tx.commit()?;
|
||||
drop(conn);
|
||||
let _ = self.events.send(MessageEvent::Sent {
|
||||
seq: self.next_seq(),
|
||||
from: "reminder".to_owned(),
|
||||
to: agent.to_owned(),
|
||||
body: message.to_owned(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue