Skip to content

fix(sidecar): serve long-form audio in its own lane, with per-model batch cost caps - #628

Open
ShaiShmuel wants to merge 12 commits into
mainfrom
fix/sidecar-audio-lane
Open

ShaiShmuel wants to merge 12 commits into
mainfrom
fix/sidecar-audio-lane

Conversation

@ShaiShmuel

@ShaiShmuel ShaiShmuel commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  1. Before fix(sidecar): bound costly request waiting #708, the sidecar's batch former packed pending work cheapest first, with no aging (Whisper: the longest recordings wait minutes, and short clips wait for long-form audio in the same batch #585).
    • Under load a long recording kept losing to shorter requests and could time out.
    • fix(sidecar): bound costly request waiting #708 now moves the oldest request that has waited past the batch window to the front.
    • A clip batched with a long recording still waits for all of it.
  2. fix(batcher): serve long-form audio in its own lane, alternating with clips #601 added a runs-alone lane to the Python batcher. This PR ports it to the sidecar.
  3. On its own, the lane starved clips, because every sidecar model shared one cost cap of 16384. The Python worker uses each model's max_batch_tokens instead, which is 720000 ms of audio for Whisper large-v3-turbo and Parakeet-TDT.
  4. The engine now reports each model's max_batch_tokens when the model is ready. The sidecar sizes that model's cost cap and adaptive range with the Python worker's formula.
  5. At the 180000 ms adaptive floor, a clip turn could still leave a long clip over. Later turns sorted it behind newer, cheaper clips, so it was never served. Main before fix(sidecar): bound costly request waiting #708 never served it either. A clip turn now owes the clips that earlier turns left over.

Net effect:

  • Long recordings stop timing out.
  • While long-form audio is pending, every clip is served within a bounded number of turns, at any cost cap.
  • Models on the default 16384 budget keep today's caps. That is 232 of 268 encode, score and extract profiles.

Results

These runs used one L4, with the sidecar in front of sie-server, comparing main d680237 with this branch. Both sides predate #708, and the runs were not repeated after the merge. Whisper large-v3-turbo unless noted.

load main this PR
8 long-form clients 5 timeouts, max 231 s 0 timeouts, max 95 s
16 clip + 4 long-form clients 0 recordings served, 4 timed out 22 served, 0 timed out
same load, clips median 1.3 s, 2 timeouts median 25.7 s, 0 timeouts
Parakeet-TDT, 16 clip clients 66 audio-s/s 158 audio-s/s
  • The clip median under mixed load is the price of fairness.
  • While a recording is pending, the merge with fix(sidecar): bound costly request waiting #708 forms the same batches as before. A property test checks this. The clip-only Parakeet row now also gets fix(sidecar): bound costly request waiting #708's promotion, and was not re-measured.
  • The left-over fix did not move the live numbers. In those sessions no turn left a clip over, because the cap stayed at 720000, so the tests below are what cover it. There were 0 request errors and 0 OOMs, and no request over 30 s shared a batch.
  • Overload trade-off, from a closed-loop simulation:
    • At 180000 ms, the worst clip wait drops from up to 1791 s to 30-61 s.
    • At 65536 ms with 48 clip clients, the median rises and 24-35% fewer clips beat a 120 s client timeout.
    • With the defaults, a speech model's cap adapts between 180000 and 2880000 ms. It reaches 65536 ms only in these cases:
      • SIE_BATCHER_MAX_BATCH_COST=65536, which sets every model's budget.
      • SIE_ADAPTIVE_BATCH_MAX_COST below 180000, which holds the cap there from the first batch.
      • SIE_ADAPTIVE_BATCH_MIN_COST at or below 65536, which lets the cap adapt down under load.
      • A backend that reports no budget, which starts at 16384 and adapts between 4096 and 65536.

Changes

Tests

  • Sidecar, 95e06bd: fmt and clippy (-D warnings) are clean.
    • The lib has 728 passed and 2 ignored, and the bin has 14 passed.
    • The integration suites pass: byte_identity, cli_help, integration_smoke, local_ingest_loopback, nats_auth and readyz_http.
  • New tests:
    • The 180000 ms review case: the 30 s clip went from 0 serves in 300 batches to one every 2 turns.
    • A randomized property test over 24 seeds, each run with and without aging. It checks per-batch caps, cost order and every clip's wait bound, with caps between 4096 and 720000. While a recording stays pending, the aged runs form the same batches as the unaged ones.
    • Closed-loop latency tests at 180000, 16384 and 4096 ms.
    • With fix(sidecar): bound costly request waiting #708:
      • A recording that has waited longest still waits for the clip turn under way.
      • The turn after the last recording still serves its clips cheapest first, and the oldest clip goes first once that turn ends.
      • Outside the lanes, batches match main's packing with and without aging, over 20 seeds.
      • Removing the guard fails these tests.
  • Candle worker and Python IPC tests: 200 passed and 264 passed at 469a4cb. Nothing they cover changed since.

For review

  • Per-model caps are on by default, for Python parity, and operator overrides still win.
  • Pipeline depth stays 2, including Helm's explicit setting. Per-model depth is a separate follow-up.
  • Is a higher clip median under overload the right price for a bounded worst case?

Refs #585, #601, #708.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Team
  • Run ID: d108bd1e-bbf8-41c1-a49c-a76208bd7d15
📥 Commits

Reviewing files that changed from the base of the PR and between 469a4cb and 95e06bd.

📒 Files selected for processing (8)
  • packages/sie_server/src/sie_server/_ipc_test_harness.py
  • packages/sie_server/src/sie_server/ipc_server.py
  • packages/sie_server/src/sie_server/queue_executor.py
  • packages/sie_server/tests/test_ipc_server.py
  • packages/sie_server/tests/test_queue_executor.py
  • packages/sie_server_sidecar/docs/architecture-guide.md
  • packages/sie_server_sidecar/src/dispatcher.rs
  • packages/sie_server_sidecar/src/scheduler/batch_former.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/sie_server_sidecar/docs/architecture-guide.md

Included review availability: This review used your included allowance. 9 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour.

📝 Walkthrough

Walkthrough

The change adds optional model batch-cost budgets to readiness responses and uses them to configure sidecar schedulers. It also changes prepared-audio cost calculation and batch formation so long recordings run alone while recording and batchable lanes take alternating turns.

Changes

Model budgets and sidecar scheduling

Layer / File(s) Summary
Readiness budget reporting and propagation
packages/sie_server/src/sie_server/*, packages/sie_server/tests/*, packages/sie_server_rust/src/*, packages/sie_server_sidecar/src/protocol/*, packages/sie_server_sidecar/src/dispatcher.rs, packages/sie_server_sidecar/src/backend/router.rs, packages/sie_server_sidecar/docs/architecture-guide.md
Python and Rust readiness responses now include an optional max_batch_tokens value. The sidecar dispatcher passes the reported value to scheduler resolution. Tests cover ready, absent, and older wire responses.
Per-model scheduler budgets and updates
packages/sie_server_sidecar/src/scheduler/{batch_config,adaptive,engine,registry}.rs, packages/sie_server_sidecar/src/lib.rs, packages/sie_server_sidecar/src/dispatcher.rs, packages/sie_server_sidecar/docs/architecture-guide.md
The registry uses a positive reported model budget unless a valid environment override pins the cost. Schedulers derive adaptive ranges from the selected budget and adopt changed reported budgets. Environment lookup is injectable.
Prepared long-recording turns
packages/sie_server_sidecar/src/audio_prep.rs, packages/sie_server_sidecar/src/scheduler/{item,batch_former,registry}.rs, packages/sie_server_sidecar/docs/architecture-guide.md
Prepared extract audio uses duration-based cost. Audio above the 30-second sample threshold runs alone. Batch formation alternates runs-alone and batchable lanes, tracks turn membership, and prioritizes carried-over requests.

Sequence Diagram(s)

sequenceDiagram
  participant CandleBackend
  participant Dispatcher
  participant ProductionSchedulerRegistry
  participant Scheduler
  CandleBackend->>Dispatcher: readiness response with max_batch_tokens
  Dispatcher->>ProductionSchedulerRegistry: resolve scheduler with model budget
  ProductionSchedulerRegistry->>Scheduler: create or adopt cost budget
Loading

Suggested reviewers: krisztian-gajdar

Priority: ⬆️ High

Merge Risk: ⚪ Minimal · up to 95e06

Models can now report their own batch budgets, and long audio recordings are scheduled in their own turns alongside short clips. When a model reports no budget, the previous behavior is preserved. No concrete defect was identified, so the change looks ready to merge.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 67.98% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 178 functions across 19 files. (1 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the two primary changes: a dedicated lane for long-form audio and per-model batch cost caps.
Full details: Docstring Coverage

Explanation

Docstring coverage is 67.98% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 178 functions across 19 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@svonava

svonava commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Heads-up on a sidecar change I'm about to open nearby. No action needed here; it is meant to compose with this PR.

Problem. On the sidecar path, SGLang OCR extract (LightOnOCR-3-4B, GLM-OCR) costs up to twice as much as on the worker's direct path. The scheduler packs up to 12 pages into one RunBatch, a batch answers only when its slowest page finishes, and pipeline depth 2 plus the 4-slot IPC pool cap the pages in flight. #675 fixed the same thing on the direct path.

Planned change:

  • Python reports the worker's dispatch width as an optional max_concurrent_dispatch on ModelDescriptor. It goes on the descriptor, not on EnsureModelReadyResponse, so it does not touch your max_batch_tokens field.
  • In dispatcher.rs, for a model whose width is above 1:
    • the drain loop sends each formed extract batch as single-item RunBatch calls;
    • the model's pipeline depth becomes max(depth, width).
  • ipc_client.rs grows the slot pool by that width.
  • Nothing under scheduler/ changes (batch_former, registry, engine, adaptive, item, batch_config).

Overlap with this PR. Only dispatcher.rs is shared. My hunks are in the drain loop and the readiness handling, not in resolve_scheduler, and the test-only EnsureModelReadyResponse literals don't change.

After both land. The split could move onto your runs-alone lane: an extract item of an engine-batched model would report runs_alone(). That needs the item to know its model's width, so I've kept the split in the dispatcher for now.

ShaiShmuel and others added 8 commits October 11, 2026 22:11
The sidecar batch former sorts pending work by cost, shortest first, so a
long recording kept being skipped while shorter requests arrived, and
clips packed with long-form audio waited for the whole batch to finish.

Prepared audio longer than 30 s (Whisper's feature window) now runs
alone: it never shares a batch, and such items are served one per batch
in arrival order. While other items are pending too, the two lanes take
turns: a cost-sorted batch of the other items, then the oldest long
recording. Before any batch has been taken, the first one comes from the
lane holding the oldest pending item. This is the rule the Python
batcher adopts in #601.

Batch formation is unchanged when nothing pending runs alone. Cost
(audio duration in ms), the cost, request and hard audio caps, flush
reasons and timer re-anchoring are unchanged.

Refs #585

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Python batcher serves long-form audio with the same runs-alone lane
since #601. What gets flagged differs: Python flags audio only in the
Whisper adapter, at its 30 s feature window, while the sidecar flags
every prepared audio item longer than 30 s, whatever the model, Parakeet
included.

State this in the batch former's port-contract header, next to the 30 s
threshold in audio preparation, and in the architecture guide's
scheduling section.

Refs #585

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a debug "scheduler batch formed" line where the batch former drains a
batch: flush reason, lane (alone or batched), batch size and cost, and the
pending, pending-alone and remaining counts. This is the sidecar
counterpart of the lane field in the Python batcher's "Batch formed" debug
log, so batch composition and lane turns can be read from the scheduler's
own log.

No behaviour change.

Refs #585

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sidecar built every model's scheduler from one global batch config,
so every model ran a 16384 cost cap and the adaptive cost range 4096 to
65536 derived from it. The Python worker sizes both from the model's own
max_batch_tokens. Speech models count cost in audio milliseconds and
declare 720000, so the shared cap held a clip batch to one or two clips;
with the runs-alone lane alternating clip batches and long recordings,
clips starved under load.

EnsureModelReadyResponse gains an optional max_batch_tokens. The
scheduler registry creates each model's scheduler from it: the static
cost cap starts at the budget, and the adaptive controller derives its
range with Python's formula (floor min(max(256, budget / 4), budget),
ceiling 4 * budget, start at the budget). One clip turn now takes every
pending clip up to the request count cap.

Precedence: SIE_BATCHER_MAX_BATCH_COST, when set, still pins the cap and
range for every model; otherwise the reported budget applies; otherwise
16384. Backends that do not report a budget, and models whose budget is
16384, behave as before. SIE_ADAPTIVE_BATCH_*_COST overrides still apply
on top. When a model later reports a different budget, its scheduler
re-bases every batcher and rebuilds its controller; record_completion
now steps under the controller lock so the two cannot interleave.

Other profiles change to match the Python path, for example 4096 or 8192
for some vision and cross-encoder models and 1 for extractors that take
one document per batch.

Refs #585

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EnsureModelReadyResponse gains an optional max_batch_tokens: the budget
from the model's profile, in the model's cost units (tokens for text,
milliseconds for audio). It is filled on the ready path only, from the
worker's static WorkerConfig.max_batch_tokens rather than the batch
config cost that the direct-path adaptive controller rewrites as it
steps.

The worker-sidecar sizes the model's batch cost cap and adaptive cost
range from it, as ModelWorker does for its own batcher. Sidecars that do
not know the field ignore it.

Refs #585

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With long-form audio pending, the batch former alternated one batch of
batchable items with one long recording. The sidecar's request count cap
is 12, against Python's 64, so once each model sizes its own cost cap the
count cap bounds a clip turn instead. When more clips were pending than
one batch takes, the cost sort left the longest clips behind every turn,
and with clients that resubmit at once they could wait indefinitely: the
starvation from #585, now limited to the costliest clips.

A batchable turn now serves the batchable items that were pending when it
began, cheapest first, up to the cost cap it began with. One Python batch
takes the same items. The request count cap and drain budgets split the
turn into batches. Items that arrive during the turn wait for the next
one. A turn begins after each long recording runs, even before the next
recording is pending, so the clips that waited behind it go first.

Batch formation is unchanged while no long recording is pending and no
turn is under way. Python's turn stays one batch; the batch former
documents the difference.

A closed-loop model in the tests serves 16-48 clip clients and 1-4
long-form clients one batch at a time for 30 min, with drain budgets
cutting some extracts short. The longest wait for a clip drops from
893-1810 s to 17-28 s. Recordings wait a little longer, since a clip
turn can now take several batches: at most 15-16 s instead of 13 s with
one long-form client, and 58-80 s instead of 52 s with four.

Refs #585

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…atch

A scheduler's static cost cap started at the model's budget even when
SIE_ADAPTIVE_BATCH_MAX_COST or SIE_ADAPTIVE_BATCH_INITIAL_COST clamped
the adaptive controller below it. Until the first controller step, after
creation and again after every re-base, batches could pack up to the
full budget: 720000 ms of audio for a speech model, where an operator
may have set 65536. The static cap now starts at the controller's
starting cost, which is the budget unless one of those overrides clamps
it, so nothing changes without overrides.

The registry, the batch config and the controller now read their
variables through an injectable lookup (SchedulerRegistry::from_lookup;
from_env passes the process environment). Tests can then cover the
precedence without touching the process environment:
SIE_BATCHER_MAX_BATCH_COST set to an unsigned integer wins over a
reported budget; unset or unparseable, the reported budget applies, and
16384 when none is reported.

Refs #585

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…delReady

The Candle worker's EnsureModelReadyResponse gains the optional
max_batch_tokens the Python server already sends. On the ready path it
carries the effective max_batch_tokens of the profile the model id routes
to, following extends. A worker-sidecar in front of a Candle pool then
sizes each model's batch cost cap and adaptive range from the model's
own budget instead of the 16384 default. For example,
prithivida/Splade_PP_en_v2:candle declares 8192. Other states leave the
field unset, and readers that do not know it ignore it.

Refs #585

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ShaiShmuel
ShaiShmuel force-pushed the fix/sidecar-audio-lane branch from 80c76fa to f94b2d8 Compare October 11, 2026 20:31
A batchable turn of the runs-alone lane served the clips pending when it
began, cheapest first, up to the cost cap it began with. The clips it left
were sorted again by cost in the next turn, behind the cheaper clips that
had arrived meanwhile. At a speech model's adaptive floor (180000 ms), with
18 resubmitting 10 s clients filling every turn, a 30 s clip was never
served.

A turn now owes the clips earlier turns left over: the oldest, whatever its
cost, and more of them, oldest first, while they fit the cost cap together.
Its budget is the cost cap plus the oldest one's cost. It takes its other
clips cheapest first while what is left of the budget still covers what it
owes, and the owed clips join the batch at which the next cheapest clip
would leave too little for them. Every turn therefore serves the oldest
left-over clip, so a clip is served within n + 1 turns of its arrival,
where n counts it and the older clips still pending when its first turn
ended; later arrivals never add to n.

Batches stay in cost order and stop only at the cost cap, the request
count cap, a drain budget or to keep room for owed clips, so a costly
left-over clip neither cuts a batch short nor joins the cheapest clips
ahead of their turn. A left-over clip above the cost cap (possible at
16384 ms and below, for backends that report no budget) runs alone and,
thanks to the extra budget, no longer takes the whole turn from the
cheaper clips. Until a turn has taken a clip it does not owe, it takes its
cheapest one even above what is left, as a turn's first batch always did.
A turn takes at most its cost cap plus two clips, and recordings still
alternate with turns. Packing outside turns is unchanged.

Closed-loop simulation (16, 32 and 48 clip clients, 4 recording clients,
30 minutes, 3 seeds), against cost-first turns:
- 180000 ms: worst clip wait 30-61 s instead of up to 1791 s; median 14-31 s
  instead of 14-15 s; up to 10% more clips and up to 3% fewer recordings.
- 65536 ms: worst clip wait 53-146 s instead of the whole run; median
  25-68 s instead of 13 s.
- 16384 ms: worst clip wait at most 533 s instead of the whole run; median
  13-36 s instead of 12 s; 1.8-2.4 times as many clips.
- 4096 ms: worst clip wait at most 559 s instead of the whole run and
  70-84% more clips, but the median rises from 12-164 s to 97-231 s.
- 720000 ms: unchanged.

Tests: the 180000 ms boundary case; deterministic cases for cost order
around owed clips, an owed clip above the cost cap, and the turn after the
last recording; a randomized audit of the wait bound, cost order,
cheapest-first order, room for owed clips, full batches and per-batch caps
under replenishment, moving caps and drain budgets; closed-loop latency at
180000, 16384 and 4096 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ShaiShmuel
ShaiShmuel marked this pull request as ready for review October 12, 2026 12:20
@ShaiShmuel
ShaiShmuel requested a review from a team as a code owner October 12, 2026 12:20
@ShaiShmuel
ShaiShmuel requested a review from huronat October 12, 2026 12:20
coderabbitai[bot]
coderabbitai Bot previously approved these changes Oct 12, 2026
huronat
huronat previously approved these changes Oct 12, 2026

@huronat huronat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 469a4cb. No blocking issue found.

The carry-over reservation addresses the previously reported starvation case at the 180000 audio-cost floor: over 300 extracted batches, the 30-second clip is now served 50 times, with short clips and recordings continuing to make progress. Independently ran the sidecar library suite: 721 passed, 2 ignored. Required CI is green.

I support per-model batch cost budgets by default, retaining explicit operator overrides and the existing safety caps. Keep configurable per-model/profile pipeline depth as a separate follow-up; this PR leaves depth 2 unchanged, including Helm's explicit setting. When composing this with #708, preserve the clip-turn reservation and validate the combined scheduler behavior.

Non-blocking documentation correction: the low-cap overload trade-off can also be reached through SIE_ADAPTIVE_BATCH_MAX_COST, even when the backend reports a 720000 budget. GPU performance results were not independently rerun in this review.

Codex review, posted at Attila's request.

ShaiShmuel and others added 3 commits October 12, 2026 19:45
Brings the branch up to main at 8ec90e1, including #708 (aged
promotion) and #714 (serde-saphyr).

#708's aged promotion moves into order_for_next_batch and applies only
outside batchable turns with no runs-alone request pending, which is
where packing is point 3's. Inside a turn, what the turn owes already
bounds every clip's wait, and a promoted recording or late clip would
break the lanes. The lane test harness keeps aging out of reach, because
its arrival times are simulated while aging reads the real clock. #708's
new test backend gains max_batch_tokens: None.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anes

Point 3's aged promotion applies only outside batchable turns with
nothing flagged pending. Lanes::aged makes every request count as aged,
which is deterministic, unlike the real-clock wait window.

- A recording that has waited longest still waits for the clip turn
  under way.
- The turn after the last recording still serves its clips cheapest
  first. Once it ends, the oldest clip goes first again.
- The cost-sorted packing reference models the promotion, and runs with
  and without aging.
- Both lane property tests run with and without aging. While a recording
  stays pending, the aged run must form the same batches as the unaged
  one.

Dropping the turn check fails the turn-after-the-last-recording test and
the first property test. Dropping the whole guard fails both new tests
and both property tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Point 3, the Python comparison and try_drain_up_to's doc now say that
nothing is promoted during a batchable turn or while a runs-alone item
is pending. "Caps and flush triggers" is restored as #708 had it. The
overload note names SIE_ADAPTIVE_BATCH_MAX_COST as another way to a low
cap, and notes that point 3 makes the same trade between turns. The
architecture guide no longer says batches outside turns are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ShaiShmuel
ShaiShmuel dismissed stale reviews from huronat and coderabbitai[bot] via 95e06bd October 13, 2026 00:48
@ShaiShmuel

Copy link
Copy Markdown
Contributor Author

@huronat #708 landed first, so this branch now merges main at 8ec90e1 and composes the two. The push dismissed your approval. Here is what changed since 469a4cb:

  • c8aa483 is the merge. fix(sidecar): bound costly request waiting #708's aged promotion moves into order_for_next_batch and applies only outside clip turns, while no long recording is pending. Inside a turn, the clip-turn reservation is unchanged. fix(sidecar): bound costly request waiting #708's test backend gains max_batch_tokens: None.
  • 6933300 adds tests for both sides of that line. Both lane property tests now run with aging on and off. While a recording stays pending, the aged runs form the same batches as before. Removing the guard fails these tests.
  • 95e06bd updates the docs, including your SIE_ADAPTIVE_BATCH_MAX_COST note.

We also ran a closed-loop simulation of the combined behaviour, which is not committed:

  • It found no lane or reservation violation in any load.
  • With recordings always pending, the batches are identical to 469a4cb's.
  • Between turns, fix(sidecar): bound costly request waiting #708 now bounds the wait of a costly clip that cost order alone kept passing over.

@ShaiShmuel
ShaiShmuel requested a review from huronat October 13, 2026 01:09

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants