test(miner): add real crash-recovery test for portfolio-queue stuck items - #5469
Conversation
…tems (JSONbored#4868) The existing suite only exercised sweepStuckItems/findStuckItems in-process against fake timers. Spawns a real Node child process that claims the only queued item, then idles forever with no cleanup handler; the test SIGKILLs it and verifies the item stays genuinely stuck until its lease expires, then is swept back to queued and re-claimable.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5469 +/- ##
==========================================
- Coverage 94.71% 94.67% -0.04%
==========================================
Files 556 556
Lines 44546 44546
Branches 14664 14664
==========================================
- Hits 42192 42175 -17
- Misses 1619 1636 +17
Partials 735 735
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-12 21:52:40 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 5 non-blocking
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
[BETA] Chat with GittensoryAsk Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Summary
in_progress-item crash-recovery scenario against a real crashed process — the existing suite (test/unit/miner-portfolio-queue-expiry.test.ts) only exercisessweepStuckItems/findStuckItemsin-process against fake timers, never an actual killed OS process.test/unit/miner-portfolio-queue-crash-recovery.test.ts, mirroring the fixture-child-process pattern fromtest/unit/miner-worktree-allocator-collisions.test.tsandtest/unit/miner-concurrent-store-races.test.ts(Add a real concurrent-process test for ledger races #4867, merged): spawn a real Node child process that claims the only queued item viadequeueNext()(stamping a real on-disk lease), report the claim, then idle forever with no cleanup handler — simulating a process that claims work and crashes mid-attempt. The testSIGKILLs the child and asserts the full recovery cycle:in_progresson disk.queued.dequeueNext()— full crash → detect → reclaim → re-claim cycle.test/fixtures/miner-concurrent-stores/claim-and-hold-child.mjs(added to the existingminer-concurrent-storesfixtures directory from Add a real concurrent-process test for ledger races #4867 rather than a new directory, since it's the same claim-and-race fixture family).sweepStuckItems/reclaimStuckItem, already shipped under Add lease/timeout/reclaim to portfolio-queue's stuck items #4827) — it does not touch, and is not extended into, cross-miner claim-conflict resolution, which stays maintainer-only.Fixes #4868
Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally — this change lives entirely undertest/unit/**/test/fixtures/**exercisingpackages/gittensory-miner/**, which sits outside vitest'scoverage.includeglob today, socodecov/patchcannot measure it directly — consistent with the existing worktree-allocator/claim-ledger cross-process collision tests.npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run build:minernpm run test:miner-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:testnpm run ui:buildnpm audit --audit-level=moderateThis PR is the test addition: 2 new tests (the real crash → sweep → reclaim → re-claim cycle, including both the too-soon-to-sweep and past-the-bound-to-sweep sides of the expiry check; plus a fixture-argument-validation guard), driving the real store via a real spawned-and-killed
nodechild process against a real on-disk SQLite file. Ran the new file 4 times in a row locally to check for timing/kill-signal flakiness — stable every time (2/2 passing, ~0.4–0.7s total).Safety
UI Evidencesection below — N/A, no visible/UI change.UI Evidence
Not applicable — this PR only adds a crash-recovery integration test for the portfolio-queue store; there is no visible UI change.
Notes
dequeueNext()'s own return shape carries noleasedAtfield (onlylistInProgress()'s lease-annotated projection does) — the fixture script callslistInProgress()right after claiming to capture the real stamped lease time the test needs to compute expiry windows against. This is a pre-existing, intentional asymmetry inportfolio-queue.js(not something this PR changes), just something the fixture had to account for.packages/gittensory-miner/lib/portfolio-queue.jsorportfolio-queue-expiry.jsis touched — this is purely a test/fixture addition on top of the already-shipped Add lease/timeout/reclaim to portfolio-queue's stuck items #4827 lease/sweep mechanism.