You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[ENH](worker): Widen async fn windows to the furthest fitting compaction boundary (#7621)
## Why
An async attached function drains its input collection one compaction
window at a time. Each run reads the records between the function's
completion offset and one compaction boundary, sends them to the
external generation service, waits for it to finish, and advances the
offset to that boundary. When a tenant backfills a large history, the
collection accumulates dozens of small compactions — and the function
replays them one by one, paying a full generation round-trip (minutes
each, dominated by remote wall time) for every ~200-record window.
The resolver currently picks the *nearest* boundary above the completion
offset, so the number of round-trips equals the number of compactions,
no matter how small each one is. In production we have observed exactly
this shape: a backfill of tens of thousands of records drains in
hundreds of serial multi-minute round-trips, taking the better part of a
day for a single collection.
## What
The boundary resolver now targets the *furthest* live compaction
boundary whose window still fits within `max_compaction_size`, and falls
back to the nearest boundary (preserving the existing oversized-window
error) when none fits. One run then covers every compaction between the
completion offset and that boundary. With a window cap of 10,000
records, a dense backlog of ~200-record compactions drains in up to ~50×
fewer generation round-trips.
No other component changes:
- The plan already only carries an upper bound for the log read and the
as-of record segment at the completion offset; nothing downstream
requires the target to be the immediately-next version
(`log_fetch_orchestrator` sets
`pulled_log_offset`/`log_upper_bound_offset` from the plan, and the
completion offset advances to exactly that target via
`resolve_pulled_log_offset`).
- Skipped intermediate boundaries retire safely in the work queue:
`CheckInvocationStatus` marks any queued entry done once the function's
completion offset passes it.
- Log retention already holds back garbage collection to the minimum
attached-function completion offset
(`fetch_min_attached_function_completion_offset` in the garbage
collector), and a widened window reads no older logs than today — same
start, further end.
- The HTTP generation executor already splits any window into multiple
requests capped at 16MB / `batch_size` (`batch_requests` in
`http_generate.rs`), so window size and request payload size stay
decoupled.
Changed:
`rust/worker/src/execution/orchestration/async_function_boundary.rs`
(`resolve_boundary_plan_from_version_file`).
## Tests
`cargo test -p worker --lib async_function_boundary` — 10 passed. New
cases: furthest boundary picked when several fit; oversized boundaries
skipped in favor of the widest fitting one; error unchanged when no
boundary fits; deleted versions never become widened targets;
offset-zero backfill now targets the widest fitting boundary.
## Future work: bounded per-function pipelining
Fattened windows fix the round-trips-per-record ratio but keep one
window in flight per function, so remote generation latency still
serializes a single tenant's drain. Pipelining K windows per function is
the next lever (a large backfill's drain time drops roughly by K), but
it is not a local change: concurrent runs resolve from the same
persisted completion offset today (they would process the same window,
not consecutive ones), the offset advance would need low-water-mark
semantics in sysdb to tolerate out-of-order completion, and the
generation service's tolerance for out-of-order windows is a contract
that lives outside this repo. Deferred until those are settled.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
0 commit comments