Skip to main content

Module wrappers

Module wrappers 

Source
Expand description

Composable op dispenser wrappers.

Each wrapper lives in its own submodule under this directory, and the module file is named for the YAML field that triggers it — poll.rs for poll:, rate.rs for rate:, and so on. The mod.rs holds shared traits/types plus the wrappers still awaiting extraction; submodules are re-exported here so the existing crate::wrappers::<Name> import paths keep working.

A wrapper declares itself to the registry with a crate::wrapper_registry::WrapperName and the owned_fields that select it (see crate::wrapper_registry). At op construction the resolver composes the ones whose fields are present into a cascade around the adapter’s dispenser, innermost-first, subject to each wrapper’s requires_inner / forbids_outer constraints.

§The wrappers

Ordered innermost-to-outermost, which is also the order a cycle passes through them on its way to the adapter and back:

YAMLmodulewhat it does
tries:triesAttempt loop. The absolute innermost layer: wraps the raw adapter dispenser, owns the retry budget and the per-attempt panic catch. Absent tries:, it is not constructed at all and the op runs once.
traverse:traverseResult traversal. Counts result elements and bytes, walks declared capture points, and writes extracted values onto the per-fiber op-template kernel. On by default and installed even when nothing requires it; result: / metrics: additionally declare it requires_inner, which the composition resolver enforces at init. Like result: the block CUSTOMISES rather than selects: path: re-roots the body with a base JSON Pointer so captures stop repeating an envelope prefix, and on_missing: ignore|warn|error decides what an unresolved capture means.
delay:delaySleeps before and/or after the inner op, reading the interval per cycle through the pull plan. u64 is nanoseconds, f64 is milliseconds.
poll:pollRe-executes the inner op until its ROW COUNT — optionally projected through a JSON Pointer — lands in [min_rows, max_rows], or the timeout fires. The await primitive for backend state such as a compaction drain. Note the asymmetry with PHASE-level poll: (nmbrs_workload::model::PhasePollSpec), whose until: is a polydat boolean expression re-evaluated per iteration; the op-level wrapper has no such condition form and can only test a row count.
if:r#ifConditional execution. A falsy per-cycle value skips the op entirely — no inner execution, no adapter call — and counts a skip.
while:r#whileLoops the inner op while a per-cycle predicate holds.
result:resultExposes op-result fields, plus the magic externs body / count / ok, as Polydat wires on the op-template kernel. Always installed; the optional result: block OVERRIDES which fields are exposed rather than enabling the wrapper — which is why it is not in the registry’s owned_fields.
metrics:metricsRecords synthetic metrics. After the adapter returns, pulls each declared metric’s value through the op-template kernel and writes it to the instrument. Also resolves cell: placement, materialising one dimensional cell per coordinate value.
rate:ratePer-op rate limiter, independent of the activity-level limiter and of every other op’s. Each instance owns its own limiter and acquires on every dispatch.
fields:fieldsPrints the rendered op text per cycle — the “what did this op actually send” surface.
readout:readoutOpt-in per-op status visibility: reports an op-level lifecycle (start / complete / fail) so a long op appears as its own timed leaf rather than silence.
memo:memoPublishes a short human-visible string to the activity’s memo slot before and/or after the op — the [[ … ]] line.
gutter:gutterPublishes the phase’s contextual left-gutter cell from polydat templates. Distinct from memo, which owns the memo line.
errors:errorsError routing. The outermost OP-level wrapper: it sees the one terminal outcome of the whole stack and applies the op’s error policy (warn / count / stop).
dryrun:dryrunShort-circuit: returns an empty result without calling the adapter. Its field is spelled like the others, but is normally INJECTED by the runner onto every op template from the CLI dryrun=<mode> param rather than written in a workload. It forbids_outer on memo and gutter, which is why those two hold explicit slots in the default order.
interval: / repeat:intervalThe one PHASE-level wrapper. Re-runs a whole phase, dwelling interval between runs and bounded by repeat. Not an OpDispenser — it wraps the phase seam, so there is no dispenser type to re-export.

Composition order is not alphabetical or declaration order: it comes from wrapper_resolver::DEFAULT_ORDER plus the constraint graph, and a workload may override it with wrappers: / --wrap-default-order. Two placements are load-bearing rather than cosmetic — tries is hand-placed innermost so the plan matches runtime truth, and memo/gutter must sort inside dryrun or resolution fails with ForbiddenOuter.

Re-exports§

pub use dryrun::DryRunWrapper;
pub use memo::MemoDispenser;
pub use gutter::GutterDispenser;
pub use delay::DelayDispenser;
pub use if::ConditionalDispenser;
pub use while::WhileWrapper;
pub use rate::OpRateWrapper;
pub use fields::FieldsDispenser;
pub use poll::PollingDispenser;
pub use poll::PollingMetrics;
pub use readout::ReadoutDispenser;
pub use result::ResultDispenser;
pub use metrics::MetricsDispenser;
pub use traverse::TraversalStats;
pub use traverse::TraversingDispenser;
pub use tries::TriesDispenser;
pub use errors::ErrorHandlerDispenser;

Modules§

condition
The one predicate mechanism.
delay
Per-cycle delay wrapper. Reads delay values through the cycle’s pull plan and sleeps before and/or after delegating to the inner op. u64 → nanoseconds; f64 → milliseconds.
dryrun
Dryrun short-circuit wrapper.
errors
Error-handler wrapper — the OUTERMOST op-level wrapper (SRD-82 Part 3b).
fields
Fields wrapper — prints the rendered op text per cycle.
gutter
Gutter wrapper — publishes the phase’s contextual left-gutter cell from workload-declared polydat templates.
if
Conditional execution wrapper. Reads a per-cycle truthy/falsy value through the pull plan; if falsy, the op is skipped (no inner execution, no adapter call) and skips_total is incremented on the activity metrics.
interval
Interval wrapper — the first PHASE-level wrapper (SRD-82/92 cross-level; see docs/cross-level-wrapper-cascade-scope.md). interval: is its sigil: re-run this phase, dwelling interval between runs, bounded by repeat:.
memo
Memo wrapper — publishes a short human-visible string to the activity’s memo ArcSwap before / after the inner op runs.
metrics
Synthetic-metric recorder (SRD-40b §6). After the inner adapter returns, pulls each declared metric’s value through the per-fiber op-template kernel via ctx.wires.get and records it onto the kind-specialised instrument (gauge / histogram / counter).
poll
Polling / await wrapper. Re-executes the inner op until its row count (optionally projected through a JSON-Pointer path) falls into the configured [min_rows, max_rows] window, or the timeout fires. Used for waiting on backend state to settle: SAI index build, compactions, etc.
rate
Per-op rate limiter. Independent of the activity-level rate limiter and of every other op’s per-op limiter — each OpRateWrapper instance owns its own RateLimiter and acquires from it on every dispatch.
readout
readout wrapper (SRD-63) — opt-in per-op status visibility.
result
Result-as-GK adapter (SRD-40b §5). After the inner adapter returns its OpResult, this wrapper exposes declared op-result fields plus the magic externs (body, count, ok) as Polydat named wires on the per-fiber op-template kernel via ctx.wires.write. Sits between the inner adapter and the metrics layer in the wrapper stack.
traverse
Default result-traversal wrapper. Always wraps the inner adapter dispenser: counts result elements + bytes, walks declared capture points, and writes extracted values onto the per-fiber op-template kernel via ctx.wires.write.
tries
Tries wrapper — the CONDITIONAL innermost op-level wrapper (SRD-82 Part 3b). tries: is its sigil: the TOTAL number of attempts an op may make.
while
Loop-while wrapper. Iterates the inner op as long as the op-template’s while: Polydat expression evaluates truthy. On each iteration the wrapper: