test: harden reconnect-restart-in-place test against dash-spv lock-release race#910
Merged
Merged
Conversation
…lease race
`reconnect_restart_in_place_reuses_backend` intermittently failed CI
(v1.0-dev and every open PR built on it) with
`SpvError("Data directory locked: ... already in use by another process")`.
Root cause: `WalletBackend::stop_in_place()` documents that
`pwm.spv().stop()` releases the dash-spv storage advisory lock before
returning, but the underlying OS-level flock's release is not always
synchronous with that call under load — the test's immediate reconnect
can lose a race against its own just-stopped predecessor. The upstream
`platform-wallet` crate collapses the underlying error into an opaque
`SpvError(String)`, so structural matching (and thus a production-side
fix) isn't available without string-parsing, which this repo's
conventions forbid.
Replace the single reconnect assertion with a bounded, blind retry
(up to 6 attempts, capped exponential backoff) so the test asserts the
durable restart-in-place contract without being sensitive to this
transient timing window. A genuine regression still fails loudly once
the retry budget is exhausted. Scope is limited to this one test — the
other two `backend_reopen_lock()` users exercise a different resource
(SqlitePersister single-open registry via a fresh AppContext) and
never call `.start()` twice on the same backend instance, so they are
unaffected.
Verified: 20/20 passes in a tight loop (Codex Sol), reconfirmed 15/15
after a doc-comment wording touch-up; full workspace suite green;
clippy and fmt clean.
Co-Authored-By: Codex Sol <noreply@openai.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
lklimek
marked this pull request as ready for review
July 20, 2026 08:34
Collaborator
|
✅ Final review complete — no blockers (commit b36521f) |
thepastaclaw
approved these changes
Jul 20, 2026
thepastaclaw
left a comment
Collaborator
There was a problem hiding this comment.
Final validation — Codex + Sonnet
Bounded, blind, capped-backoff retry (max 6 attempts) correctly absorbs a documented dash-spv storage-lock release timing race in a single offline test, without weakening the restart-in-place regression contract (still panics loudly on exhaustion). Verified against the exact head SHA; no in-scope issues found by either agent.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (completed),gpt-5.6-sol— rust-quality (completed) - Verifier:
claude-sonnet-5— final-verifier - Sonnet reviewers:
claude-sonnet-5— general (completed),claude-sonnet-5— rust-quality (completed)
Claudius-Maginificent
marked this pull request as draft
July 20, 2026 09:56
lklimek
marked this pull request as ready for review
July 20, 2026 09:57
lklimek
enabled auto-merge (squash)
July 20, 2026 09:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why this PR exists
context::wallet_lifecycle::tests::reconnect_restart_in_place_reuses_backendintermittently fails CI withSpvError("Data directory locked: ... already in use by another process"). Confirmed pre-existing onv1.0-devitself (run 29638976177) and independently affecting every currently-open PR built on top of it (fix(shutdown): stop wallet backend on GUI close and clear stale shutdown-channel log #905, fix: re-enable shielded transactions now that mainnet supports protocol v12 #906, feat(migration): auto-refresh DAPI nodes during pre-1.0 migration #908) — a shared/correlated CI-red issue, not caused by any of those PRs.v1.0-devhas a non-deterministic chance of a red "Tests" check on an otherwise-correct change, forcing needless re-runs and eroding trust in CI signal.WalletBackend::stop_in_place()documents thatpwm.spv().stop()releases the dash-spv storage advisory lock (LockFile,dash_spv::storage::lockfile) before returning, but the underlying OS-levelflock's release isn't always synchronous with that under load — the test's immediate reconnect-in-place can lose a race against its own just-stopped predecessor. The upstreamplatform-walletcrate collapses the underlying error into an opaquePlatformWalletError::SpvError(String), so a structural (non-string-parsing) production-side fix isn't available from this repo without either a string-parsing hack (forbidden by this repo's conventions) or a change to the upstream crate (out of scope here).What was done
reconnect_restart_in_place_reuses_backendwith a bounded, blind retry (up to 6 attempts, capped exponential backoff 25ms→400ms) aroundensure_wallet_backend_and_start_spv. A genuine restart-in-place regression still fails loudly once the retry budget is exhausted — the retry does not inspect or match on error content (no string-parsing), it just retries any failure.backend_reopen_lock()users (issue7_fresh_persistor_bip44_xpub_matches_det_bridge,cold_boot_hydrates_persisted_transaction_history_without_live_events) exercise a different resource (theSqlitePersistersingle-open registry via a freshAppContext) and never call.start()twice on the same backend instance, so they're unaffected by this race and were left untouched.Testing
cargo test --all-features --workspace: full suite green.cargo clippy --all-features --all-targets -- -D warnings: clean.cargo +nightly fmt --all -- --check: clean.Breaking changes
None — test-only change, no production behavior affected.
Checklist
Attribution
🤖 Co-authored by Claudius the Magnificent AI Agent
Summary by CodeRabbit