Skip to main content

vane_core/
flow_ctx.rs

1use std::sync::Arc;
2
3use tokio_util::sync::CancellationToken;
4
5use crate::flow_log::{FlowLogSink, FlowLogVerbosity, TrajectoryBuilder};
6
7/// Per-walk execution context. Constructed once per L4 connection (and
8/// re-constructed per L7 request when a hyper service-fn dispatches into
9/// the L7 sub-graph). Fields are *owned* — no lifetime parameter — so the
10/// struct survives `tokio::spawn` and `move` closures (notably hyper's
11/// service-fn closure at `Node::Upgrade`, which captures `log` / `cancel`
12/// / `verbosity` per request).
13///
14/// `Arc<dyn FlowLogSink>` and `CancellationToken` clone cheaply (each is
15/// internally an `Arc`), and `tracing::Span` is also `Arc`-backed; the
16/// per-request clones in the hyper bridge are O(1).
17pub struct FlowCtx {
18	pub span: tracing::Span,
19	pub log: Arc<dyn FlowLogSink>,
20	pub cancel: CancellationToken,
21	/// Verbosity selected when this connection was accepted. The listener
22	/// reads `engine::VerbosityState` once at `FlowCtx` construction;
23	/// in-flight connections retain the value they were built with.
24	pub verbosity: FlowLogVerbosity,
25	/// Walker-internal step accumulator. The executor pushes one entry
26	/// per node-visit and emits a single `FlowLogKind::Trajectory` event
27	/// from `finalize()` at terminate or error.
28	pub trajectory: TrajectoryBuilder,
29}
30
31#[cfg(test)]
32mod tests {
33	use parking_lot::Mutex;
34
35	use super::*;
36	use crate::conn_context::ConnId;
37	use crate::flow_log::FlowLogEvent;
38	use crate::ir::NodeId;
39
40	struct NullSink {
41		count: Mutex<u32>,
42	}
43
44	impl FlowLogSink for NullSink {
45		fn emit(&self, _event: FlowLogEvent) {
46			*self.count.lock() += 1;
47		}
48	}
49
50	// Compile-gate: a FlowCtx must be constructible from a concrete sink
51	// wrapped in `Arc<dyn FlowLogSink>`, alongside an owned tracing::Span
52	// and CancellationToken, plus the verbosity / trajectory fields the
53	// walker reads. Field visibility regressions break this.
54	#[test]
55	fn flow_ctx_accepts_arc_dyn_sink_and_owned_fields() {
56		let sink: Arc<dyn FlowLogSink> = Arc::new(NullSink { count: Mutex::new(0) });
57		let span = tracing::Span::none();
58		let cancel = CancellationToken::new();
59		let ctx = FlowCtx {
60			span,
61			log: sink,
62			cancel,
63			verbosity: FlowLogVerbosity::Trajectory,
64			trajectory: TrajectoryBuilder::new(ConnId(0), NodeId::new(0), 0),
65		};
66		let _ = &ctx.span;
67		let _ = &ctx.log;
68		let _ = &ctx.cancel;
69		let _ = &ctx.verbosity;
70		let _ = &ctx.trajectory;
71	}
72}