Skip to content

fix(heartbeat): dedupe concurrent process_lost reaps - #913

Merged
kkroo merged 1 commit into
masterfrom
fix-heartbeat-reaper-cas
Aug 1, 2026
Merged

fix(heartbeat): dedupe concurrent process_lost reaps#913
kkroo merged 1 commit into
masterfrom
fix-heartbeat-reaper-cas

Conversation

@kkroo

@kkroo kkroo commented Aug 1, 2026

Copy link
Copy Markdown

Thinking Path

  • Paperclip is the app/control plane used to coordinate AI agent work and track each agent run through the heartbeat runtime.
  • The server heartbeat service owns orphaned-run recovery, including the process_lost reaper and the Prometheus counter that pages on sustained loss.
  • Production logs showed the same heartbeat run IDs being reaped multiple times within seconds while the alert numerator continued to climb.
  • The metric was intentionally emitted after the status write, but the write used the unconditional setter, so concurrent reaper invocations could each finalize and count the same already-running row.
  • The service already had a compare-and-swap helper for running-run finalization; the reaper needed to use it and skip terminal side effects when it loses that race.
  • This pull request makes process_lost minting idempotent under concurrent reapers and adds a regression test that releases two reapers against the same run at once.
  • The benefit is a more trustworthy process_lost alert and fewer duplicate retries/events from one underlying lost run.

Linked Issues or Issue Description

No standalone GitHub issue exists for this production incident. Bug details follow the bug-report template inline.

What Changed

  • Changed the orphan reaper process_lost finalization path to use setRunStatusIfRunning() instead of the unconditional status setter.
  • Added a loser branch that clears local tracking for already-terminal rows and skips duplicate process_lost metrics, wakeup status changes, retries, run events, and issue-promotion side effects.
  • Added a regression test that runs two concurrent reapers against the same local run and asserts only one reap/event is recorded.

Verification

  • corepack pnpm --filter @paperclipai/server typecheck
  • corepack pnpm exec vitest run server/src/__tests__/heartbeat-process-recovery.test.ts -t "deduplicates concurrent process_lost reaps" attempted locally; the file skipped because embedded Postgres support failed to initialize on this host with Postgres init script exited with code 1. The data directory might already exist. CI should execute the test on a healthy embedded-Postgres runner.
  • git diff --check
  • Production short-window metric check showed no fresh claude_k8s/opencode_k8s pre-adapter process_lost churn while this fix was prepared.

Risks

  • Low migration risk: no schema or data migration.
  • Behavioral risk is constrained to the orphan reaper's duplicate-race path. The first reaper to transition running -> failed still performs the existing terminal side effects.
  • If a run remains running after a failed CAS unexpectedly, this patch skips that reaper pass; a later periodic reap can try again.

Model Used

OpenAI Codex, GPT-5 coding agent, tool-using mode with local shell, Kubernetes, Prometheus, GitHub CLI, and TypeScript typecheck verification.

Checklist

  • I have included a thinking path that traces from project context to this change
  • I have specified the model used (with version and capability details)
  • I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work
  • I have searched GitHub for duplicate or related PRs and linked them above
  • I have either (a) linked existing issues with Fixes: # / Closes # OR (b) described the issue in-PR following the relevant issue template
  • I have run tests locally and they pass
  • I have added or updated tests where applicable
  • If this change affects the UI, I have included before/after screenshots
  • I have updated relevant documentation to reflect my changes
  • I have considered and documented any risks above
  • All Paperclip CI gates are green
  • Greptile is 5/5 with no open P2s, recommendations, or follow-ups
  • I will address all Greptile and reviewer comments before requesting merge

@cursor

cursor Bot commented Aug 1, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@allyblockcast

allyblockcast Bot commented Aug 1, 2026

Copy link
Copy Markdown

Hey @kkroo! Before this PR can be reviewed, a few things need attention:

Missing or incomplete:

  • Missing section: ## Thinking Path
  • Missing section: ## What Changed
  • Missing section: ## Verification
  • Missing section: ## Risks
  • Missing section: ## Model Used
  • No linked issue or inline issue description found — either tag an existing issue with Fixes #NNN / Closes #NNN / Refs #NNN, or describe the underlying issue inline in the PR body following one of our issue templates (https://github.com/paperclipai/paperclip/tree/master/.github/ISSUE_TEMPLATE). See CONTRIBUTING.md → "Link Issues or Describe Them In-PR".
  • Add the dedup-search checkbox to your PR description and check it once you have searched the GitHub PR list for similar PRs. See the PR template at .github/PULL_REQUEST_TEMPLATE.md and CONTRIBUTING.md → "Before You Start: Search First".

Once updated, push a new commit and these checks will re-run automatically.

— commitperclip

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@kkroo
kkroo force-pushed the fix-heartbeat-reaper-cas branch from 3c0dded to f82cdfd Compare August 1, 2026 09:54
@kkroo
kkroo merged commit 5c580c7 into master Aug 1, 2026
14 of 15 checks passed
@kkroo
kkroo deleted the fix-heartbeat-reaper-cas branch August 1, 2026 09:57
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