aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ln.ts
Commit message (Collapse)AuthorAgeFilesLines
* ln: tear down dead cl clients fully + recover invoice listener on socket deathAdam Soltys2026-08-151-10/+46
| | | | | | | | | | | | | | | | | Replace bare `client = null` with dropClient(): stop the clightning-client library's internal reconnect loop (clear reconnectTimeout, neuter reconnect, destroy the socket, drop listeners). A dead client was otherwise orphaned and spun forever retrying `connect ENOENT`, spamming logs and leaking a socket+timer on every cl restart. Guard the error handler on `c === client` so a stale client's late error can't drop a newer, healthy one. Add lnListen.onDrop so the invoice listener recycles immediately when its long-poll socket dies (bump epoch, re-arm) instead of waiting up to 5 minutes for the stall watchdog. Stop counting LightningUnavailableError toward the listener's process.exit escalation, so a cl restart no longer makes the app self-exit — it retries until cl returns. Co-Authored-By: Claude Opus 4.8 <[email protected]>
* ln/lightning: watchdog recycles zombie receive-listener socketAdam Soltys2026-06-041-0/+16
| | | | | | | | | | | | | | | | | | | | | On 2026-06-04 cl restarted (autoheal, after its 15s healthcheck timed out), and the app's waitanyinvoice long-poll hung on the now-dead listen socket. listenerActive stayed true forever, so ensureListenerAlive never restarted it, and incoming lightning payments stopped crediting for ~2h until a manual app restart. The per-call RPC timeout in ln.ts can't catch this: waitanyinvoice is intentionally in NO_TIMEOUT (it's meant to block). Fix: ensureListenerAlive (runs every 120s) now also detects a stalled listener — active but blocked in waitanyinvoice for >5min. It probes cl via the main ln socket (getinfo); only if cl is actually alive does it treat the listen socket as a zombie, call lnListen.reset() (new: drops the proxy's socket so the next call reconnects), and re-arm. A listenerEpoch guard makes the wedged invocation bow out when its waitanyinvoice finally rejects, so we never run two listeners concurrently and never double-credit. Verified with a state-machine test covering normal receive, quiet-but-healthy (left alone), stall+cl-alive (recycled), stall+cl-down (left alone), and the no-double-listener race. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* ln: time out short-lived RPCs so a hung cl reconnects without restartAdam Soltys2026-05-311-2/+64
| | | | | | | | | | | | | | | | | | A unix-domain RPC socket has no TCP keepalive, so if cl goes unresponsive while the socket stays open (zombie/half-open), an awaited call hangs forever — the "stuck spinner past /pay/bob, no error" symptom. Nothing threw, so the existing reconnect-on-error path never fired and only an app restart recovered it. Wrap short-lived calls in a 30s Promise.race timeout (matching health.ts). A timeout rejects with ETIMEDOUT, now part of isSocketDied, so the client is dropped and the next call reconnects — no process restart. Long-polls (waitanyinvoice et al), in-flight payments (pay/xpay/sendpay/keysend), and bolt12 round-trips (fetchinvoice/ sendinvoice/offer) are exempt: timing those out client-side would risk leaked debits or break intentional blocking. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* adjust ln minfeeregtest-dataAdam Soltys2026-03-151-1/+1
|
* handle socket errorsAdam Soltys2026-02-251-0/+38
|
* health checkAdam Soltys2026-02-061-1/+5
|
* more robust lightning clientAdam Soltys2025-12-161-3/+85
|
* xpayAdam Soltys2024-11-271-1/+1
|
* save ecash idAdam Soltys2024-10-241-5/+3
|
* typescriptAdam Soltys2024-08-261-0/+7