Skip to content

fix: coordinate reminders across processes#3

Open
kernel-oops wants to merge 1 commit into
zelenkovsky:mainfrom
kernel-oops:fix/cross-process-reminder-leases
Open

fix: coordinate reminders across processes#3
kernel-oops wants to merge 1 commit into
zelenkovsky:mainfrom
kernel-oops:fix/cross-process-reminder-leases

Conversation

@kernel-oops

Copy link
Copy Markdown

Summary

Prevent independent OpenCode processes on the same host from submitting the same persisted reminder occurrence concurrently.

  • claim each reminder occurrence with an atomic cross-process lease before prompting
  • reconcile losing processes to the winner's persisted recurrence so they retain future failover timers
  • serialize cancellation and post-prompt persistence with a short-lived per-reminder mutation lock
  • atomically publish reminder JSON and owner records to avoid partially visible state
  • recover leases only when the owner is demonstrably dead (Linux PID + /proc start identity)
  • preserve the existing startup behavior that advances genuinely missed recurring occurrences without prompting
  • make startup cleanup generation-conditional so stale snapshots cannot delete newer recurrences

Scope and delivery semantics

This coordinates processes on one host sharing a local filesystem with atomic hard links, exclusive creation, and rename. It does not claim cross-host/NFS safety.

Prompt delivery remains at-least-once across the unavoidable ambiguity where prompt acceptance succeeds but a process, storage, or lock failure prevents the durable post-prompt transition. True crash-proof exactly-once delivery would require an idempotency key supported by the prompt API. These boundaries, conservative stale-lock behavior, and the cancellation race after durable validation are documented in the README.

Tests

  • concurrent in-process and independent-process lease acquisition: exactly one owner
  • independent scheduler processes: exactly one prompt for one persisted occurrence
  • recurring loser reconciliation and dead-owner recovery
  • conditional startup cleanup against a newer generation
  • cancellation interleavings around post-prompt mutation
  • overdue-restoration versus ordinary late-timer behavior
  • malformed/transient persistence reads and post-acceptance save failure
  • atomic reminder replacement and temporary-file cleanup
  • child-process timeout/failure cleanup

Verified locally:

bun test test/leases.test.ts test/storage.test.ts test/scheduler.test.ts
38 pass, 0 fail

bun test
67 pass, 0 fail

bun x tsc --noEmit
pass

git diff --check
pass

The lease test was also repeated five times successfully.

Relationship to #2

This PR is intentionally based directly on main and fixes a separate cross-process ownership problem. PR #2 addresses same-process cancellation/generation races. Both touch scheduler.ts, index.ts, and related tests, so they will require a deliberate integration after either merges; this PR does not claim to include #2's prompt-abort behavior.

@kernel-oops

Copy link
Copy Markdown
Author

A consolidated integration PR is now available at #5. It deliberately combines #2, #3, and #4, resolves their overlapping scheduler changes, and adds regression fixes found while stress-testing the combined lifecycle. This PR is left open for history/discussion, but the consolidated PR is the recommended merge path.

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.

2 participants