Skip to content

M21.3: watcher survives mempool transport failures and recreates - #189

Merged
n8bar merged 1 commit into
mainfrom
claude/m21-3-watcher-findings
Sep 6, 2026
Merged

n8bar merged 1 commit into
mainfrom
claude/m21-3-watcher-findings

Conversation

@n8bar

@n8bar n8bar commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Fixes #187 and #188, both surfaced by the M21.3 log inspection.

#187 — watcher aborts on a mempool transport failure

Http::pool() returns the ConnectionException itself in a slot when that request fails at the transport level; MempoolClient::transactionsForAddresses() called ->ok() on it and the whole wallet:watch-payments run died with Call to undefined method ConnectionException::ok(). A slot that is not a Response is now treated like a non-2xx reply: the existing warning is logged with the exception message, that address returns [], and the rest of the batch proceeds.

New test tests/Feature/Wallet/MempoolClientTest.php fakes a failedConnection for one address and asserts the other address still returns its transactions, no exception escapes, and the warning is logged once.

#188 — scheduler mutex survives a container recreate

  • bootstrap/app.php: withoutOverlapping(10) so a stranded mutex clears within one interval plus a margin instead of 24 h. ScheduleTest now asserts expiresAt === 10.
  • scripts/deploy.sh: runs php artisan schedule:clear-cache right after up -d so a deploy cannot leave the watcher parked even before the expiry lands; a failed clear only warns (the script runs under set -e, and services are already up at that point). Also drops the retired "alpha" wording from the compose-file comment.
  • docs/ops/RUNNING_THE_SERVER.md: "Reading health honestly" gets a bullet on the stranded-mutex symptom and the post-recreate check.

Verification

  • PR Tests (GitHub Actions) are green.
    Note: Codex's inline runner may show "vendor/autoload.php missing." That's expected; use the PR checks instead.

Local: ./vendor/bin/sail artisan test — 635 passed (2654 assertions).

Note: pint --test flags MempoolClient.php, but every hunk is pre-existing style on main (constructor braces, concat spacing, !$x); no added line is flagged and CI does not run pint, so the file was left as-is rather than reformatting unrelated code in a bugfix PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_012bBptf9B3BtyeQaTWMrosd

Two findings from the M21.3 log inspection.

#187: MempoolClient::transactionsForAddresses() called ->ok() on every
Http::pool() slot, but a transport-level failure leaves the
ConnectionException itself in that slot, so the call threw and the whole
wallet:watch-payments run aborted before recording completion. A slot
that is not a Response is now treated like a non-2xx reply: warn with
the exception message, return [] for that address, keep the batch.

#188: the watcher's withoutOverlapping mutex used the 24 h default, so
recreating the scheduler mid-run (every deploy) parked the watcher for a
day with every container reading healthy. The mutex now expires in 10
minutes, deploy.sh clears stranded scheduler mutexes right after
`up -d`, and the runbook's "Reading health honestly" section says what
to confirm after any recreate. Also drops the retired "alpha" wording
from the deploy script comment.

Fixes #187
Fixes #188

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012bBptf9B3BtyeQaTWMrosd
@n8bar
n8bar merged commit 030cdc1 into main Sep 6, 2026
1 check passed
n8bar added a commit that referenced this pull request Sep 6, 2026
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.

Payment watcher aborts when a mempool request fails (ConnectionException has no ok())

1 participant