Expand description
A Rust stream-processing library: build a directed acyclic graph of data transformations once, then run it against live data or replay it over history with identical semantics.
use std::time::Duration;
use wingfoil::prelude::*;
use wingfoil::{NanoTime, RunFor, RunMode};
let g = GraphBuilder::new();
let count = g.ticker(Duration::from_millis(10)).count();
let is_even = count.map(|n: &u64| n.is_multiple_of(2));
let total = count.filter(&is_even).fold(0u64, |acc, v| *acc += v);
let mut runner = g.build();
runner.run(RunMode::HistoricalFrom(NanoTime::ZERO), RunFor::Cycles(10)).unwrap();
assert_eq!(runner.value(&total), 2 + 4 + 6 + 8 + 10);Swap RunMode::HistoricalFrom for RunMode::RealTime and the same graph
runs against the wall clock — that is the point of the two run modes.
§The idea: node semantics as a function, not an object
An Op defines what a node does as a pure associated
function — cycle(cfg, state, input, ctx) — over engine-owned state and
typed inputs the engine passes in, with a const ACTIVATION declaring how
it is scheduled. Nothing about a node’s computation is tied to how its
storage is allocated or how its inputs are fetched.
That separation is what lets one definition drive several execution strategies, and it is the property the whole design is arranged around:
- the interpreted engine (
interp::Builder) owns the value slots and the state, adapts eachOpbehind a single dyn boundary, and drives theKernel; - a compiled runner is a plain function with node state in local
variables, calling the same
Op::cyclefunctions monomorphized, with tick propagation asbools the optimiser can see through; - a nested island packs a whole sub-graph into one node of an interpreted graph, running that same compiled code inside it.
Every one of those executes the identical semantics code. There is no
duplicated cycle logic anywhere — no per-kind emitter strings, no
cycle_inline twins — so the strategies cannot drift from each other.
nitro! is the front door: one wiring function in, all
three out.
§The tour
nitro!— one wiring function, three execution paths from the same tokens:interpreted(), fully-monomorphizedcompiled(), andnested()(a compiled island as one node of an interpreted graph).fluent— the chaining API as extension traits (SourceOpsfor sources,StreamOpsfor combinators), so the op vocabulary is open;preludebrings the common set into scope.ops— the op catalog (map/filter/fold/join/delay/window/… plus the sources), andadapters::statistics— EWMA and rolling-window statistics as a separate opt-inStatisticsOpstrait. An op is single-sourced through one mechanism:#[op(build = name)]on itsOpimpl generates the interpretedBuildermethod and thenitro!forwarder functions every compiled/nested emission dispatches through, both derived from the op’s declared shape — there is no per-op table in the macro, so built-in and user ops take the identical path.- Sources in every activation mode:
Activation::THREADEDexternal, busy-spinActivation::ALWAYSpoll, the both-modeschannel, andfeedbackedges. All non-coalescing: same-instant values ride oneBurst, never latest-wins. adapters— the I/O surface (CSV, Kafka, ZeroMQ, KDB+, Redis, Postgres, etcd, FIX, web, Aeron, iceoryx2, Fluvio, augurs, Prometheus, OTLP), each behind its own feature and kept out of the prelude — opt in withuse wingfoil::adapters::<name>::….latency— stamp wall-clock timestamps onto messages as they hop through ops and across processes, then aggregate per-stage deltas.introspect— the wired topology as data and as pictures (Graphviz / Mermaid / JSON / GML), fromGraphBuilder::snapshotorRunner::snapshot. Active and passive edges are drawn differently, which is usually the reason to want the picture.channel— theMessageenvelope and senders;async_source(theasyncfeature) wraps it asproduce_async, an async producer of timestamped values that replays deterministically in historical mode.pool— recycled payload buffers behind cheap non-atomicPooledhandles, and the loan-basedpooled_channelproducer API: zero payload allocations at steady state, with the bounded pool as backpressure.- Fallible lifecycle — every
Opfunction returnsanyhow::Result; the interpretedRunnerreports the firststart/cycle/stop/teardownerror with node context and still runs cleanup.
For how the pieces fit together, and why, see
docs/wingfoil-architecture.md.
§Threading: a graph lives on one thread
GraphBuilder, Stream<T> and
Runner are !Send and !Sync. They hold Rc
internally, so wiring, build and
run all have to happen on the same thread, and
moving any of them into std::thread::spawn is a compile error along the
lines of:
error[E0277]: `Rc<RefCell<wingfoil::interp::Builder>>` cannot be sent
between threads safely
= help: within `{closure@...}`, the trait `Send` is not implemented for
`Rc<RefCell<wingfoil::interp::Builder>>`
note: required because it appears within the type
`wingfoil::fluent::GraphBuilder`(Whichever of the three you moved: Stream<T> names the same Rc, and
Runner names the Rc slots it owns.)
That is a deliberate contract, not a missing impl. Node state is
RefCell-owned by the engine and read back through Rc slots precisely so
that no lock is ever taken on the graph execution path — a mutex inside
cycle would be a correctness problem as much as a cost one. Making the
wiring types Send would only move the synchronisation somewhere less
visible.
Nothing stops you running several graphs, one per thread. What you cannot do is share one.
§Crossing the thread boundary
Every supported crossing hands you a Send half while the graph stays
where it is:
| You want to… | Wire | The Send half to move |
|---|---|---|
| feed a graph from a thread, socket or async task | channel | ChannelSender<T> |
| …the same, with recycled buffers and no payload allocation | pooled_channel | PooledSender<T> |
| …the same, but connect at run start rather than at wiring | source_at_start | ChannelSender<T>, handed to your setup |
| run a whole producer sub-graph on a worker thread | spawn | nothing — the worker wires its own graph |
| offload one stage of an existing pipeline | spawn_map | nothing — ditto, in lock-step |
| push values in from realtime code, minimal envelope | external | ExternalSource<T> |
channel is the general answer, and the one
the I/O adapters are built on. The sender is Send and clonable, each
send wakes the realtime kernel, and
send_at stamps a value so a historical
replay stays deterministic:
use std::thread;
use std::time::Duration;
use wingfoil::prelude::*;
use wingfoil::{NanoTime, RunFor, RunMode};
let g = GraphBuilder::new();
// The `Stream` stays on this thread; the `ChannelSender` is the `Send` half.
let (values, sender) = g.channel::<u64>();
let total = values
.map(|b: &Burst<u64>| b.iter().sum::<u64>())
.fold(0u64, |acc, v| *acc += v);
let mut runner = g.build();
let producer = thread::spawn(move || {
for i in 1..=3u64 {
sender.send_at(i, NanoTime::from(Duration::from_secs(i)));
}
// End-of-stream: the receiving graph winds down once it has drained.
sender.close();
});
runner.run(RunMode::HistoricalFrom(NanoTime::ZERO), RunFor::Forever).unwrap();
producer.join().unwrap();
assert_eq!(runner.value(&total), 1 + 2 + 3);Note what did not cross: g, values, total and runner all stayed on
the calling thread. If the producer is itself a wingfoil graph, reach for
spawn instead and it will wire and run one on
the worker for you — see examples/core/threading and examples/core/spawn.
§Tracing and instrumentation
The engine can emit tracing spans around its own execution. Every span
site is behind its own feature, and the tracing dependency itself is
optional, so a default build carries neither the dependency nor a single
span:
| feature | what it adds |
|---|---|
tracing | The tracing dependency. On its own it emits nothing — enable one of the below. |
instrument-run | A span around Runner::run (and run_dynamic, under dynamic-graph) — the whole start→cycles→stop→teardown lifecycle. |
instrument-cycle | A span around each engine cycle (one per dirty-node batch). |
instrument-apply-nodes | A span around each lifecycle phase (start / stop / teardown) applied over all nodes, recording the phase in desc. |
instrument-initialise | A span around graph initialisation (Builder::build). |
instrument-cycle-node | A span per node execution, recording the node index and label. High frequency — opt in deliberately. |
instrument-default | instrument-run + instrument-cycle + instrument-apply-nodes + instrument-initialise. |
instrument-all | instrument-default plus instrument-cycle-node. |
All instrument-* features imply tracing. Both dispatch strategies (the
sparse drain and the FullSweep oracle) emit
the same spans, so instrumentation cannot tell them apart — just as results
cannot. See examples/core/tracing for a runnable demonstration, and
StreamOps::logged for the per-value debug tap
(which emits through the log crate, independently of these features).
§Known limits
Documented, not forgotten: merge/join are fixed at two inputs on the
compiled path (the interpreted side has variadic merge_n); the
interpreted value store is per-node slots rather than an arena/SoA, and its
dirty list is drained rather than topologically ordered; and compiled()
is a closed box — static topology, outputs only, no I/O or live inputs, by
design. See docs/planning/port-plan.md “Deferred / post-v1 work”.
Re-exports§
pub use log;
Modules§
- adapters
- I/O adapters — the graph’s edges to the outside world, built strictly on
the public Op-pattern API (sources over
channel/poll, sinks overfor_each). - channel
- The channel layer: cross-thread / cross-process value transport with a
typed
Messageenvelope, ported onto the Op model (Phase 3). - fluent
- Fluent wiring sugar: the legacy wingfoil chaining style
(
ticker(d).count().map(f).filter(&cond)) over the explicitBuildercore. - interp
- The interpreted engine: dynamic wiring and execution of
Ops. - introspect
- Static graph introspection: the wired topology as data, and as pictures.
- latency
- Latency capture for wingfoil — stamp wall-clock timestamps onto messages as they hop through ops (and across processes), then aggregate the per-stage deltas at the end of the pipeline.
- op
- The
Optrait: node semantics as pure, monomorphizable functions. - ops
- The core op vocabulary. Each op is a zero-sized witness type carrying
semantics in associated functions — never instantiated. Compare each
cyclebody with the correspondingMutableNodeimpl in the main crate: the logic is identical, but here it is written once and executed by every engine, interpreted or compiled. - pool
- Pooled payloads: recycled buffers behind cheap graph-side handles, and the
loan-based channel producer API (
pooled_channel). - prelude
- The common wiring vocabulary, re-exported for
use wingfoil::prelude::*. - runtime
- The shared runtime core: engine time, run bounds, the scheduled-callback
queue, the burst grouping type and the
Kernelthat drives a run. - tier
Tier: which of anitro!module’s engines executes the graph.
Macros§
- __
wf_ fluent_ accumulate - Fluent wiring for [
accumulate], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_accumulate!(T);— to define theaccumulatemethod over the trait’s element typeT. - __
wf_ fluent_ buffer - Fluent wiring for [
buffer], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_buffer!(T);— to define thebuffermethod over the trait’s element typeT. - __
wf_ fluent_ collapse - Fluent wiring for [
collapse], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_collapse!(T);— to define thecollapsemethod over the trait’s element typeT. - __
wf_ fluent_ constant - Fluent wiring for [
constant], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_constant!();— to define theconstantmethod on aGraphBuilderextension trait (it is a source — no receiver stream). - __
wf_ fluent_ cumulative_ max - Fluent wiring for [
cumulative_max], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_max!();— to define thecumulative_maxmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ mean - Fluent wiring for [
cumulative_mean], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_mean!();— to define thecumulative_meanmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ mean_ time_ weighted - Fluent wiring for [
cumulative_mean_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_mean_time_weighted!();— to define thecumulative_mean_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ median - Fluent wiring for [
cumulative_median], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_median!();— to define thecumulative_medianmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ median_ time_ weighted - Fluent wiring for [
cumulative_median_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_median_time_weighted!();— to define thecumulative_median_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ min - Fluent wiring for [
cumulative_min], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_min!();— to define thecumulative_minmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ std - Fluent wiring for [
cumulative_std], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_std!();— to define thecumulative_stdmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ std_ time_ weighted - Fluent wiring for [
cumulative_std_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_std_time_weighted!();— to define thecumulative_std_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ sum - Fluent wiring for [
cumulative_sum], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_sum!();— to define thecumulative_summethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ var - Fluent wiring for [
cumulative_var], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_var!();— to define thecumulative_varmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ cumulative_ var_ time_ weighted - Fluent wiring for [
cumulative_var_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_cumulative_var_time_weighted!();— to define thecumulative_var_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ delay - Fluent wiring for [
delay], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_delay!(T);— to define thedelaymethod over the trait’s element typeT. - __
wf_ fluent_ difference - Fluent wiring for [
difference], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_difference!(T);— to define thedifferencemethod over the trait’s element typeT. - __
wf_ fluent_ distinct - Fluent wiring for [
distinct], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_distinct!(T);— to define thedistinctmethod over the trait’s element typeT. - __
wf_ fluent_ drop_ small_ change - Fluent wiring for [
drop_small_change], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_drop_small_change!(T);— to define thedrop_small_changemethod over the trait’s element typeT. - __
wf_ fluent_ enumerate - Fluent wiring for [
enumerate], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_enumerate!(T);— to define theenumeratemethod over the trait’s element typeT. - __
wf_ fluent_ ewma - Fluent wiring for [
ewma], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_ewma!();— to define theewmamethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ ewma_ half_ life - Fluent wiring for [
ewma_half_life], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_ewma_half_life!();— to define theewma_half_lifemethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ filter - Fluent wiring for [
filter], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_filter!(T);— to define thefiltermethod over the trait’s element typeT. - __
wf_ fluent_ filter_ value - Fluent wiring for [
filter_value], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_filter_value!(T);— to define thefilter_valuemethod over the trait’s element typeT. - __
wf_ fluent_ finally - Fluent wiring for [
finally], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_finally!(T);— to define thefinallymethod over the trait’s element typeT. - __
wf_ fluent_ fold - Fluent wiring for [
fold], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_fold!(T);— to define thefoldmethod over the trait’s element typeT. - __
wf_ fluent_ for_ each - Fluent wiring for [
for_each], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_for_each!(T);— to define thefor_eachmethod over the trait’s element typeT. - __
wf_ fluent_ inspect - Fluent wiring for [
inspect], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_inspect!(T);— to define theinspectmethod over the trait’s element typeT. - __
wf_ fluent_ join - Fluent wiring for [
join], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_join!(T);— to define thejoinmethod over the trait’s element typeT. - __
wf_ fluent_ join3 - Fluent wiring for [
join3], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_join3!(T);— to define thejoin3method over the trait’s element typeT. - __
wf_ fluent_ join_ passive - Fluent wiring for [
join_passive], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_join_passive!(T);— to define thejoin_passivemethod over the trait’s element typeT. - __
wf_ fluent_ limit - Fluent wiring for [
limit], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_limit!(T);— to define thelimitmethod over the trait’s element typeT. - __
wf_ fluent_ map - Fluent wiring for [
map], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_map!(T);— to define themapmethod over the trait’s element typeT. - __
wf_ fluent_ map_ filter - Fluent wiring for [
map_filter], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_map_filter!(T);— to define themap_filtermethod over the trait’s element typeT. - __
wf_ fluent_ merge - Fluent wiring for [
merge], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_merge!(T);— to define themergemethod over the trait’s element typeT. - __
wf_ fluent_ not - Fluent wiring for [
not], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_not!(T);— to define thenotmethod over the trait’s element typeT. - __
wf_ fluent_ pairwise - Fluent wiring for [
pairwise], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_pairwise!(T);— to define thepairwisemethod over the trait’s element typeT. - __
wf_ fluent_ print - Fluent wiring for
print, generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_print!(T);— to define theprintmethod over the trait’s element typeT. - __
wf_ fluent_ rolling_ max - Fluent wiring for [
rolling_max], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_max!();— to define therolling_maxmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ mean - Fluent wiring for [
rolling_mean], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_mean!();— to define therolling_meanmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ mean_ time_ weighted - Fluent wiring for [
rolling_mean_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_mean_time_weighted!();— to define therolling_mean_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ median - Fluent wiring for [
rolling_median], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_median!();— to define therolling_medianmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ median_ time_ weighted - Fluent wiring for [
rolling_median_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_median_time_weighted!();— to define therolling_median_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ min - Fluent wiring for [
rolling_min], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_min!();— to define therolling_minmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ std - Fluent wiring for [
rolling_std], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_std!();— to define therolling_stdmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ std_ time_ weighted - Fluent wiring for [
rolling_std_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_std_time_weighted!();— to define therolling_std_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ sum - Fluent wiring for [
rolling_sum], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_sum!();— to define therolling_summethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ var - Fluent wiring for [
rolling_var], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_var!();— to define therolling_varmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ rolling_ var_ time_ weighted - Fluent wiring for [
rolling_var_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_rolling_var_time_weighted!();— to define therolling_var_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ sample - Fluent wiring for [
sample], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_sample!(T);— to define thesamplemethod over the trait’s element typeT. - __
wf_ fluent_ scan - Fluent wiring for [
scan], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_scan!(T);— to define thescanmethod over the trait’s element typeT. - __
wf_ fluent_ skip - Fluent wiring for [
skip], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_skip!(T);— to define theskipmethod over the trait’s element typeT. - __
wf_ fluent_ skip_ while - Fluent wiring for [
skip_while], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_skip_while!(T);— to define theskip_whilemethod over the trait’s element typeT. - __
wf_ fluent_ step_ by - Fluent wiring for [
step_by], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_step_by!(T);— to define thestep_bymethod over the trait’s element typeT. - __
wf_ fluent_ take_ while - Fluent wiring for [
take_while], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_take_while!(T);— to define thetake_whilemethod over the trait’s element typeT. - __
wf_ fluent_ throttle - Fluent wiring for [
throttle], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_throttle!(T);— to define thethrottlemethod over the trait’s element typeT. - __
wf_ fluent_ ticked_ at - Fluent wiring for [
ticked_at], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_ticked_at!(T);— to define theticked_atmethod over the trait’s element typeT. - __
wf_ fluent_ ticked_ at_ elapsed - Fluent wiring for [
ticked_at_elapsed], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_ticked_at_elapsed!(T);— to define theticked_at_elapsedmethod over the trait’s element typeT. - __
wf_ fluent_ ticker - Fluent wiring for [
ticker], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_ticker!();— to define thetickermethod on aGraphBuilderextension trait (it is a source — no receiver stream). - __
wf_ fluent_ time_ windowed_ max - Fluent wiring for [
time_windowed_max], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_max!();— to define thetime_windowed_maxmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ mean - Fluent wiring for [
time_windowed_mean], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_mean!();— to define thetime_windowed_meanmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ mean_ time_ weighted - Fluent wiring for [
time_windowed_mean_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_mean_time_weighted!();— to define thetime_windowed_mean_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ median - Fluent wiring for [
time_windowed_median], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_median!();— to define thetime_windowed_medianmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ median_ time_ weighted - Fluent wiring for [
time_windowed_median_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_median_time_weighted!();— to define thetime_windowed_median_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ min - Fluent wiring for [
time_windowed_min], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_min!();— to define thetime_windowed_minmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ std - Fluent wiring for [
time_windowed_std], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_std!();— to define thetime_windowed_stdmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ std_ time_ weighted - Fluent wiring for [
time_windowed_std_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_std_time_weighted!();— to define thetime_windowed_std_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ sum - Fluent wiring for [
time_windowed_sum], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_sum!();— to define thetime_windowed_summethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ var - Fluent wiring for [
time_windowed_var], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_var!();— to define thetime_windowed_varmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ time_ windowed_ var_ time_ weighted - Fluent wiring for [
time_windowed_var_time_weighted], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_time_windowed_var_time_weighted!();— to define thetime_windowed_var_time_weightedmethod overStream<f64>, the concrete receiver its first edge fixes. - __
wf_ fluent_ timed - Fluent wiring for [
timed], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_timed!(T);— to define thetimedmethod over the trait’s element typeT. - __
wf_ fluent_ try_ join - Fluent wiring for [
try_join], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_try_join!(T);— to define thetry_joinmethod over the trait’s element typeT. - __
wf_ fluent_ try_ join3 - Fluent wiring for [
try_join3], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_try_join3!(T);— to define thetry_join3method over the trait’s element typeT. - __
wf_ fluent_ try_ join_ passive - Fluent wiring for [
try_join_passive], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_try_join_passive!(T);— to define thetry_join_passivemethod over the trait’s element typeT. - __
wf_ fluent_ try_ map - Fluent wiring for [
try_map], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_try_map!(T);— to define thetry_mapmethod over the trait’s element typeT. - __
wf_ fluent_ try_ map_ filter - Fluent wiring for [
try_map_filter], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_try_map_filter!(T);— to define thetry_map_filtermethod over the trait’s element typeT. - __
wf_ fluent_ window - Fluent wiring for [
window], generated by#[op(fluent)]. Invoke it inside an extension-traitimpl—__wf_fluent_window!(T);— to define thewindowmethod over the trait’s element typeT. - burst
- Macro to create a
Burst<T>with type inference. - nitro
- One wiring definition, two engines: expands to a module with
interpreted()(fluent wiring),compiled(run_mode, run_for)(fully monomorphized runner) andrun(tier, ..)(either, same outputs) emitted from the same tokens. Seewingfoil_derivefor the DSL. See the crate docs: fluent wiring in,interpreted()+compiled()out.
Structs§
- Kernel
- The shared runtime core, re-exported at the crate root: engine time, the
run bounds, the scheduled-callback queue and the
Kernelthat drives a run. The legacywingfoilcrate re-exports these same items — they are one set of types, not two — seeruntimefor why the core lives here. Clock, scheduled-callback queue and run bounds for a kernel-driven engine. See the module docs for how this relates to the interpreted engine. - Kernel
Waker - The shared runtime core, re-exported at the crate root: engine time, the
run bounds, the scheduled-callback queue and the
Kernelthat drives a run. The legacywingfoilcrate re-exports these same items — they are one set of types, not two — seeruntimefor why the core lives here. Wakes a realtimeKernelfrom another thread, marking a node dirty — the kernel-level equivalent of the interpreted engine’sReadyNotifier. Cheap to clone; hand one to each producer thread / async task. - Nano
Time - A time in nanoseconds since the unix epoch.
- Time
Queue - A time-ordered queue of
Ts, earliest first.
Enums§
- RunFor
- Defines how long the graph should run for. Can be a Duration, number of cycles or forever.
- RunMode
- Whether the graph should run in RealTime or Historical mode.
- Tier
- Which
nitro!engine executes a graph, for the generatedrun(tier, run_mode, run_for)— interpreted while developing, compiled in production, one argument apart. Which of anitro!module’s engines executes the graph. - Timer
Policy - The shared runtime core, re-exported at the crate root: engine time, the
run bounds, the scheduled-callback queue and the
Kernelthat drives a run. The legacywingfoilcrate re-exports these same items — they are one set of types, not two — seeruntimefor why the core lives here. How a realtime kernel waits out the gap to the next scheduled callback.
Functions§
- waker_
channel - The shared runtime core, re-exported at the crate root: engine time, the
run bounds, the scheduled-callback queue and the
Kernelthat drives a run. The legacywingfoilcrate re-exports these same items — they are one set of types, not two — seeruntimefor why the core lives here. Create a waker/receiver pair for external (threaded/async) sources. Hand theKernelWakerto producers and the receiver toKernel::with_ready.
Type Aliases§
- Burst
- A group of same-instant values, delivered atomically in one cycle (never
coalesced / latest-wins). A
tinyvec::TinyVec<[T; 1]>, defined here and re-exported by the legacywingfoilcrate (with itsburst!constructor macro), so both engines share one grouping type. A small vector optimised for single-element bursts. - Ready
Receiver - The shared runtime core, re-exported at the crate root: engine time, the
run bounds, the scheduled-callback queue and the
Kernelthat drives a run. The legacywingfoilcrate re-exports these same items — they are one set of types, not two — seeruntimefor why the core lives here. The receiving half of awaker_channel, to be handed toKernel::with_ready.
Attribute Macros§
- op
- Turn an
impl Op for …block into a first-class op: the interpreted wiring (an extension trait oninterp::Builder), the naming-convention forwardersnitro!’scompiled()/nested()emission dispatches through, and — withfluent— themacro_rules!that writes the op’s fluent method.