fix(heartbeat): stop logging the benign external-runtime Job deletion refusal at ERROR - #1331
Conversation
|
🔗 Paperclip issue: BLO-20482 |
1 similar comment
|
🔗 Paperclip issue: BLO-20482 |
|
Hey @allyblockcast[bot]! Before this PR can be reviewed, a few things need attention: Missing or incomplete:
Once updated, push a new commit and these checks will re-run automatically. — commitperclip |
|
@ally please review at head This PR was opened during the fleet-wide review outage tracked in BLO-26654 (codex provider quota exhaustion, from 2026-08-12T09:24Z) and has never been reviewed on either surface. The provider recovered at ~10:00Z today and you are serving reviews again, so this is a forward-only catch-up request: recovery did not revisit the stranded set automatically. Review focus: normal full pass at the head above. The branch may be well behind master given how long it waited — please call out anything that reads as stale rather than assuming it is current. |
|
@ally please review at head 041f76b — log-level change for the benign external-runtime Job deletion refusal. Focus on whether any genuinely-fatal deletion failure is now demoted below ERROR. Context: the original review request on this PR was lost during the codex provider outage (BLO-27123) — codex |
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: 041f76b
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- The split distinguishes an absent active reservation from a persisted reservation that lacks a Job identity, preserving fail-closed deletion behavior in both cases.
- The new tests exercise the cancellation cascade and verify both the benign debug path and anomalous ERROR path.
- CI's
verifyfailure is attributable to theopencode_k8s_seed_cold_startupstream lane; the other aggregate lanes and test shards passed.
Recommended Action
- No code changes requested.
… refusal at ERROR `deleteExactExternalRuntimeJob` conflated two conditions behind one `logger.error`: 1. no ACTIVE reservation at all (`reservationId: null`) -- benign. A Job only ever exists alongside a reservation carrying its name/UID, so there is nothing to target and nothing was leaked. The cancel cascade reaches this deliberately: `cancelRunInternal` notes the dispatcher may already have released a terminal run's reservation before the cascade runs. 2. a PERSISTED reservation missing its Job name/UID -- a genuine anomaly. A Job may be live that we cannot safely target. Case 1 was the only one observed in production, and it logged at ERROR, poisoning the API error rate and burying real failures. Split the branch: case 1 logs at debug, case 2 stays at error and now reports the real `reservationId` instead of a always-null expression. Both still return "mismatch", so every caller's fail-closed handling (anything other than "deleted"/"missing") is unchanged. Tests (server/src/__tests__/heartbeat-external-runtime-retry.test.ts): - "cancels a run with no active reservation without logging at error" -- fails against the unfixed source (verified), so it genuinely pins the defect rather than passing vacuously. - "still logs at error when a persisted reservation has no Job identity" -- guards the downgrade from being over-broad. Refs BLO-20482.
041f76b to
0b4936c
Compare
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: 0b4936c
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- The implementation separates an absent active reservation from a persisted reservation missing Job identity without changing the fail-closed deletion sentinel.
- The tests exercise the real cancellation cascade and assert both logging severity and the absence of a delete attempt.
- The current diff is narrowly scoped to the service branch and its regression coverage.
Recommended Action
- No code changes requested.
Thinking Path
Linked Issues or Issue Description
This PR closes only the second of that issue's two defects. The first (reclaiming queued runs whose linked issue is terminal) was found to be already implemented and deployed — the dispatch scan in
startNextQueuedRunForAgentprunes the scanned batch viaTERMINAL_ISSUE_STATUSES→evaluateQueuedRunStaleness→cancelQueuedRunForStaleIssue, verified live by token grep inside the running pod and 108 firings in 24h. Full evidence is on the issue; no code is needed for it.What Changed
server/src/services/heartbeat.ts—deleteExactExternalRuntimeJobnow distinguishes two cases instead of one:reservationis nullish) →logger.debug, message"skipping external-runtime Job deletion: no active reservation to target". A Job only ever exists alongside a reservation carrying its name/UID, so there is nothing to target and nothing leaked.cancelRunInternal's own comment records that the dispatcher may already have released a terminal run's reservation before the cascade runs, so this path is reached by design.jobName/jobUid→ stayslogger.error, and now logsreservation.idrather thanreservation?.id ?? null, which was structurally alwaysnullon the old combined branch.return "mismatch" as const, so every caller's fail-closed handling (anything other than"deleted"/"missing") is byte-for-byte unchanged.server/src/__tests__/heartbeat-external-runtime-retry.test.ts— two cases added (below). No other files touched.Verification
Automated tests —
server/src/__tests__/heartbeat-external-runtime-retry.test.ts(embedded-Postgres suite), driven through the realcancelRuncascade rather than by calling the helper directly:cancels a run with no active reservation without logging at error (BLO-20482)— asserts no ERROR emitted, exactly onedebugcarryingreservationId: null, no delete attempted, and the run reachingcancelled.still logs at error when a persisted reservation has no Job identity (BLO-20482)— guards the downgrade from being over-broad.Negative control — with the source change stashed, test 1 fails (
expected [ [ … ] ] to deeply equal []) and test 2 still passes. So test 1 genuinely pins the defect rather than passing vacuously, and test 2 correctly asserts unchanged behaviour.Production measurement (2026-08-12, Loki, scoped to
pod=~"paperclip-api-.*|paperclip-0"):reservationId: nullEvery live occurrence is the benign case this PR downgrades.
Honest caveat on severity. The issue measured ~13 per 26 min (≈720/24h) on 2026-08-01. It is now 4/24h against 22,915 total control-plane ERROR lines in the same window — 0.017%. The rate decayed ~180× on its own. The change is still correct (a benign path should not log at ERROR) but it is no longer the error-rate poisoner the issue described, and the issue's "ERROR-rate drops to zero over ≥60 min" signal can no longer discriminate fixed-from-quiet at this rate; a 72h post-deploy window is the honest check.
Risks
Low. The change is confined to log severity and one log field.
"mismatch"sentinel as before, so no caller's control flow changes. The guard still refuses to delete in exactly the same set of cases — this PR does not make deletion happen anywhere it previously did not.reservation == nullcase only.ac-Jobs, allactive=1, against 12 runningac-pods;paperclip_external_runtime_reservations_activereconciles with running runs per adapter. The refusals were not leaking Jobs.loggeris pino atlevel: "debug"with the stdout target gated atinfo, so the downgraded line leaves the error-rate signal but is still written to the log file for diagnosis — it is not deleted.Model Used
Claude Opus 5 — model id
claude-opus-5[1m](1M-token context), extended thinking enabled, with tool use (shell, GitHub API, Kubernetes read APIs, Loki queries) via the Claude Agent SDK / Claude Code harness.Checklist
external-runtime Job deletion,deletion refusal log level,persisted name and UID, andBLO-20482. No PR touches this log branch. Nearest relatives, all merged and non-overlapping: fix(heartbeat): reconcile exact external runtime Jobs #680 (introduced exact-Job reconciliation), fix(k8s): pin exact-job recovery adapter #1174 (pinned the exact-job recovery adapter), fix(k8s-job-liveness): fail closed after stale Job cleanup (BLO-20801) #1110 (fail-closed after stale Job cleanup). fix(heartbeat): stop logging the benign external-runtime Job deletion refusal at ERROR #1331 is the only PR for BLO-20482.Fixes: #/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue template0b4936c8after the rebase ontomaster: 20/20 check-runs non-failing (19 success, 1 skipped). The three ARC-eviction failures cited below are gone —verify,Canary Dry Run, andk8s-ro seed transport cold startare allsuccessat this head.mergeStateStatusisCLEAN.reviewcheck plus the Ally consolidated review, both recorded on the next line rather than claiming a tool that never ran.0b4936c8at 2026-08-15T04:05:12Z: 0 critical, 0 important, 0 suggestions, "No code changes requested." Unresolved review threads: 0. The blockingreviewcheck issuccess.