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}