Skip to content

feat(runner): settle each attempt as it finishes and refill its unit - #497

Merged
paymog merged 1 commit into
mainfrom
feat/runner-settle-on-finish
Oct 19, 2026
Merged

paymog merged 1 commit into
mainfrom
feat/runner-settle-on-finish

Conversation

@paymog

@paymog paymog commented Oct 19, 2026

Copy link
Copy Markdown
Owner

Summary

R.tick now records each attempt's outcome when that attempt finishes, gives its pool unit back, and starts the next due ticket in that unit. Before, one slow job held the whole round: the other units sat idle until it ended.

Design decisions

  • One outcome channel per round. Each attempt sends (ticket id, outcome) on a shared channel, as IO.within does in Base. The loop receives whichever answers first. Before, the loop joined per-attempt channels in list order.
  • Write-ahead order is unchanged. Each settle still appends Complete/Requeue before it changes the state and releases the grant. The next Select comes after that.
  • Fuel bound. The round's claim fuel (1 + pending at tick start) is shared by every refill, and an idle pick gives its unit back. Each attempt settles once, so the loop's settle fuel never runs out before the last attempt ends.
  • Breaker check moved to threshold 1. Outcomes now reach the breaker as they arrive. With threshold 2 and retry-after 0, the first failed job is due again before the second failure is recorded, so a third attempt is correct behavior. At threshold 1 the check keeps its intent: two jobs fail at once, and no third attempt starts.
  • Flight loses its chan field, so runner goes to 0.5.0.0. Nothing imports runner from the hub yet.

Validation

  • New check.bend scenario: capacity 2, one 1 s job, and five fast jobs. One tick runs all six. At most 2 attempts overlap in the job log, and the slow job's end is the last line. Against the old tick, this check fails: one round ran only 2 of the 6 jobs.
  • pick_bounded and pick_release still cover each claim's pool step. The log check covers the loop end to end.
  • scripts/check.sh runner passes, including the crash, compaction, and webhook scenarios. scripts/publish.sh --check passes.

Closes #443

tick now waits on one channel that every attempt answers on. Each outcome is
recorded as it arrives, its grant goes back to the pool, and the next due
ticket starts in that unit, so a slow job no longer holds the whole round.

Flight drops its per-attempt channel, so runner goes to 0.5.0.0.

Closes #443
@paymog
paymog merged commit 4188f33 into main Oct 19, 2026
4 checks passed
@paymog
paymog deleted the feat/runner-settle-on-finish branch October 19, 2026 01:22
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.

Runner: settle each attempt when it finishes, not per round

1 participant