Trim the datastream crate to its dumb-pipe core: drop the frame-timing sidecar, make mux positions gap-free for accepted frames, and simplify the endpoint fanout. - mux: defer position assignment from submit to drain so an overflowed submission no longer consumes a position (no synthetic gaps); submit now returns bool and the Mutex<Receiver> is removed since positions are assigned only to accepted frames - endpoint/mux: switch from std::sync::mpsc to crossbeam-channel and drop per-event event_matches_request filtering — request filters now apply only to the initial catalog snapshot, and future events broadcast to all subscribers - endpoint (DeliveryFanout): snapshot sender handles under the lock and deliver outside it via FanoutTarget/FanoutReport, so large batches or slow subscribers no longer block subscribe/snapshot control-plane ops - emit/endpoint/producer: drop set_frame_timing_enabled/frame_timing_enabled and the Position return from submit_record/submit_text/submit_bytes, and add submit_text_owned taking owned String - timing/lib/spec: delete the timing module and FRAME_TIME_CHANNEL/FRAME_TIME_CHANNEL_ID/FrameTimeSample re-exports (including the auto-registered timing channel in ChannelCatalogState) and renumber the DATASTREAM_SPEC.md section references across frame/ingest/store/mux - tests: remove the 567-line shared datastream_support/mod.rs harness Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
50 lines
2 KiB
Rust
50 lines
2 KiB
Rust
//! Legacy `DatastreamSink` for [`DatastreamFrame`] actor messages.
|
|
//!
|
|
//! New live transports should prefer catalog-aware [`crate::DatastreamEvent`]
|
|
//! streams. This actor remains as the counterpart to
|
|
//! [`ClusterFrameSink`](super::emit::ClusterFrameSink): a node ships positioned
|
|
//! telemetry as legacy `DatastreamFrame` actor messages over regular Swactor
|
|
//! transport, and this actor receives them, decodes each back into a
|
|
//! `(StreamId, Frame)` delivery, and hands it to a caller-supplied fold.
|
|
//!
|
|
//! It deliberately knows nothing about any view layer. The actor owns an opaque
|
|
//! callback so binaries can wire decoded deliveries into whichever fold they
|
|
//! need. Malformed payloads are dropped silently.
|
|
|
|
use swactor::actor::ActorInterface;
|
|
use swactor::runtime::Ctx;
|
|
|
|
use super::frame::{Frame, StreamId};
|
|
use super::wire::{DatastreamFrame, decode_delivery};
|
|
|
|
/// Receives legacy [`DatastreamFrame`] cluster messages and folds each decoded
|
|
/// delivery through `on_frame`. Spawn it, then publish its address under
|
|
/// [`DATASTREAM_SINK_NAME`] so legacy emitters can resolve and ship to it.
|
|
pub struct DatastreamSink {
|
|
on_frame: Box<dyn FnMut(StreamId, Frame) + Send>,
|
|
}
|
|
|
|
/// The cluster name a [`DatastreamSink`] is published under. Emitters resolve
|
|
/// this to fill their `ClusterFrameSink` destination.
|
|
pub const DATASTREAM_SINK_NAME: &str = "datastream-sink";
|
|
|
|
impl DatastreamSink {
|
|
/// Build a sink that folds every decoded delivery through `on_frame`.
|
|
pub fn new(on_frame: impl FnMut(StreamId, Frame) + Send + 'static) -> Self {
|
|
Self {
|
|
on_frame: Box::new(on_frame),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ActorInterface for DatastreamSink {
|
|
type Incoming = DatastreamFrame;
|
|
type Response = ();
|
|
|
|
fn handle(&mut self, _ctx: &Ctx, msg: DatastreamFrame) {
|
|
// Best-effort: a malformed datagram is dropped, never panics the sink.
|
|
if let Ok((stream, frame)) = decode_delivery(&msg.payload) {
|
|
(self.on_frame)(stream, frame);
|
|
}
|
|
}
|
|
}
|