1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
//! Scheduling traits: readiness and dequeue policy (EDF hooks).
//!
//! How a runtime composes `NodeSummary` (contract):
//!
//! - `readiness`
//! * Compute from **input occupancies** and **output pressure**.
//! * If all inputs empty → `NotReady`.
//! * If any input non-empty AND any output watermark ≥ soft → `ReadyUnderPressure`.
//! * If any input non-empty AND all outputs below soft → `Ready`.
//!
//! - `backpressure`
//! * Take the **max** watermark over all outputs (BelowSoft < BetweenSoftAndHard < AtOrAboveHard).
//!
//! - `earliest_deadline`
//! * If any input has an absolute deadline → use the **minimum** of present deadlines.
//! * Else if `NodePolicy.deadline.default_deadline_ns` is `Some(d)` → synthesize as `now + d`.
//! * Else → `None`.
//!
//! Notes:
//! * Watermarks come from edge occupancy snapshots (`EdgeOccupancy`), which the runtime fills
//! via `GraphApi::write_all_edge_occupancies` and refreshes via `refresh_occupancies_for_node`.
//! * Dequeue strategies (FIFO, EDF, QoS-weighted) live in runtimes; `DequeuePolicy` stays unchanged.
use crateStepResult;
use crateWatermarkState;
use crate;
/// Readiness level derived from inputs and backpressure state.
///
/// Contract followed by runtimes:
/// - `NotReady`: all inputs empty (no work).
/// - `ReadyUnderPressure`: some input available AND at least one output watermark is
/// `BetweenSoftAndHard` or `AtOrAboveHard`.
/// - `Ready`: some input available AND all outputs are `BelowSoft`.
/// A minimal summary of a node for scheduling decisions.
///
/// - `index`: the node identifier in the graph.
/// - `earliest_deadline`: minimum absolute deadline among ready inputs, or synthesized `now + default_deadline_ns`
/// if policy provides a default and inputs lack deadlines; otherwise `None`.
/// - `readiness`: derived from input availability and output pressure (see `Readiness` contract above).
/// - `backpressure`: the maximum watermark state across all outputs.
/// A dequeue policy selects the next node to run from a set of summaries.
// ---------------------------------------------------------------------------
// Concurrent worker scheduling
// ---------------------------------------------------------------------------
/// Scheduling decision for a concurrent worker.
///
/// Returned by [`WorkerScheduler::decide`] to control per-worker stepping in
/// scoped concurrent execution.
///
/// `#[non_exhaustive]` — future variants will be added as planned work lands:
/// - `StepBatch(usize)` (C1 batch semantics — step N messages in one call)
/// - `StepWithBudget { max_micros: u64 }` (R11 execution measurement)
/// Per-worker state snapshot for scheduling decisions.
///
/// Populated by the codegen-generated worker loop before each
/// [`WorkerScheduler::decide`] call. Edge occupancy is queried from concrete
/// edge types (no dyn dispatch) and summarised here.
///
/// **Extensibility model:** `#[non_exhaustive]` — fields will be added as
/// planned work lands. The codegen loop queries edges using concrete types
/// (no dyn) and populates this snapshot. The scheduler never touches edges
/// directly — it only sees the snapshot. New edge capabilities
/// (peek_header, mailbox, urgency) are exposed by adding fields here, with
/// the codegen loop doing the actual querying.
///
/// **Planned extensions (one field per planned item):**
/// - `earliest_deadline: Option<DeadlineNs>` (R1 — from peeked input headers)
/// - `max_input_urgency: Option<Urgency>` (R1 — highest urgency among inputs)
/// - `inputs_fresh: bool` (R2 — all inputs within max_age threshold)
/// - `input_liveness_ok: bool` (R5 — all inputs within liveness threshold)
/// - `micros_since_last_step: u64` (R6 — for node liveness violation detection)
/// - `criticality: CriticalityClass` (R8 — node's criticality tier)
/// - `input_count: usize` / `inputs_ready_count: usize` (C2 — N→M per-port)
/// Per-worker scheduling for concurrent execution.
///
/// Called from worker threads via **static dispatch** — the concrete scheduler
/// type is a generic parameter on `ScopedGraphApi::run_scoped`, so no `dyn`.
///
/// Sequential runtimes use [`DequeuePolicy`] (centralized, one node per tick).
/// Concurrent runtimes use `WorkerScheduler` (per-worker, one decision per step).