Skip to content

feat: reloadable refresh limits and shutdown grace - #195

Merged
blaipr merged 1 commit into
mainfrom
feat/reloadable-refresh-and-grace
Aug 26, 2026
Merged

feat: reloadable refresh limits and shutdown grace#195
blaipr merged 1 commit into
mainfrom
feat/reloadable-refresh-and-grace

Conversation

@blaipr

@blaipr blaipr commented Aug 26, 2026

Copy link
Copy Markdown
Member

What

Moves three keys off the restart-only list — they now apply on a configuration reload:

  • server.shutdown_grace_seconds — read at a single moment (the drain at shutdown), so main now takes it from the current RuntimeConfig snapshot instead of the boot config.
  • server.refresh_timeout_seconds — the refresh budget is an AtomicU64 on the coordinator, swapped by RefreshCoordinator::resize; each refresh reads it once so the gather and its timeout message agree.
  • server.refresh_max_concurrent — the semaphore resizes: a grow adds permits immediately (cancelling any pending shrink first); a shrink reclaims whatever is free now and records the rest as debt, settled at acquire() as in-flight refreshes hand permits back. Until it settles, concurrency is bounded by the old cap — the same overlap rule every other reload follows (in-flight work finishes under the configuration it started with). No background task involved.

The values live in RuntimeConfig (diffed for the reload report's applied list); application::config::apply pushes changes onto the coordinator. RestartOnlySettings shrinks to the seven keys that genuinely need a restart.

Docs

docs/config-api.md moves the three keys into the applied-by-reload table; the stale "refresh semaphore" example in CLAUDE.md's architecture note is updated.

Tests

  • Unit: resize grows/shrinks an idle pool immediately (zero clamp included), a shrink under load settles as permits return, a grow cancels pending shrink debt rather than stacking on it.
  • Integration: a reload changing all three reports them in applied with an empty restart_required, and the running process adopts the values.

server.refresh_timeout_seconds, server.refresh_max_concurrent and
server.shutdown_grace_seconds now apply on a configuration reload instead
of reporting restart_required. The refresh coordinator holds a live budget
(atomic) and a resizable semaphore: a grow takes effect immediately, a
shrink reclaims free permits now and settles the rest at acquire time as
in-flight refreshes hand theirs back. The shutdown grace is read from the
current snapshot when the drain starts.
@blaipr
blaipr merged commit acce30e into main Aug 26, 2026
6 checks passed
@blaipr
blaipr deleted the feat/reloadable-refresh-and-grace branch August 26, 2026 11:50
@blaipr blaipr mentioned this pull request Aug 26, 2026
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.

1 participant