Skip to content

Release the writer lease when Chopin is stopped while it starts - #733

Merged
lavaman131 merged 1 commit into
mainfrom
release-writer-lease-on-early-stop
Oct 28, 2026
Merged

lavaman131 merged 1 commit into
mainfrom
release-writer-lease-on-early-stop

Conversation

@lavaman131

Copy link
Copy Markdown
Collaborator

A Chopin stopped soon after it started could exit without releasing the
chopin:writer lease. The next process on the same database then refused
to start with "another Chopin instance owns the database" until the lease
expired, up to 30 seconds later.

Two gaps caused this:

  • The SIGINT and SIGTERM handlers were registered only at the very end
    of startup: after the server was already listening, and after research
    recovery and the job runner started. A stop in that window took Node's
    default action, so the process exited without running the drain that
    releases the lease. Supervisors that start Chopin, wait for it to
    answer and then stop it hit this often, especially on slower machines.
  • Startup's session reset replaces the held lease with a re-fenced one.
    A drain that ran while the reset was in flight released the old
    fencing value, which no longer matched the row.

The handlers are now registered as soon as the lease is held. The drain
waits for the session reset before it releases, and skips stopping the
HTTP server when it isn't listening yet.

Reproduced by starting Chopin, sending SIGTERM as soon as it answered
HTTP, and starting it again at once: the restart was refused 3 times in
5 before this change and 0 in 10 after it.

Assistant-model: Claude Opus 5.5 (fast)
Assistant-workflow: inline
Assistant-verification: red-before-fix passed: the new startup.test.ts case, which stops the server as soon as it holds the lease, fails without the change (lease still held after exit) and passes 8 runs in a row with it
Assistant-verification: manual scenario passed: SIGTERM as soon as Chopin answered, then an immediate restart; refused 3/5 before the fix, 0/10 after
Assistant-verification: bun test passed: GIT_CONFIG_GLOBAL=/dev/null bun test (0 fail), and the PostgreSQL lifecycle suite (122 pass)
Assistant-verification: typecheck and lint passed: bun run types and bun run ci
Co-authored-by: Alex Lavaee lavaman131@github.com

A Chopin stopped soon after it started could exit without releasing the
`chopin:writer` lease. The next process on the same database then refused
to start with "another Chopin instance owns the database" until the lease
expired, up to 30 seconds later.

Two gaps caused this:

- The SIGINT and SIGTERM handlers were registered only at the very end
  of startup: after the server was already listening, and after research
  recovery and the job runner started. A stop in that window took Node's
  default action, so the process exited without running the drain that
  releases the lease. Supervisors that start Chopin, wait for it to
  answer and then stop it hit this often, especially on slower machines.
- Startup's session reset replaces the held lease with a re-fenced one.
  A drain that ran while the reset was in flight released the old
  fencing value, which no longer matched the row.

The handlers are now registered as soon as the lease is held. The drain
waits for the session reset before it releases, and skips stopping the
HTTP server when it isn't listening yet.

Reproduced by starting Chopin, sending SIGTERM as soon as it answered
HTTP, and starting it again at once: the restart was refused 3 times in
5 before this change and 0 in 10 after it.

Assistant-model: Claude Opus 5.5 (fast)
Assistant-workflow: inline
Assistant-verification: red-before-fix passed: the new startup.test.ts case, which stops the server as soon as it holds the lease, fails without the change (lease still held after exit) and passes 8 runs in a row with it
Assistant-verification: manual scenario passed: SIGTERM as soon as Chopin answered, then an immediate restart; refused 3/5 before the fix, 0/10 after
Assistant-verification: bun test passed: GIT_CONFIG_GLOBAL=/dev/null bun test (0 fail), and the PostgreSQL lifecycle suite (122 pass)
Assistant-verification: typecheck and lint passed: bun run types and bun run ci
Co-authored-by: Alex Lavaee <lavaman131@github.com>
@lavaman131
lavaman131 merged commit a23c1e6 into main Oct 28, 2026
24 checks passed
@lavaman131
lavaman131 deleted the release-writer-lease-on-early-stop branch October 28, 2026 00:13
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