aboutsummaryrefslogtreecommitdiffstats
path: root/index.ts
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-08 22:49:26 +0000
committerAdam Soltys <[email protected]>2026-06-08 22:49:26 +0000
commit7c34b4312c8aafc7643a5192d54daea14cfc1559 (patch)
treea50cb8c940d04e15d2a6b90304e58b927ed88ae6 /index.ts
parent40d6c63cac3b59b9118abeb3b8571d0348ccfbfe (diff)
downloadcoinos-server-7c34b4312c8aafc7643a5192d54daea14cfc1559.tar.gz
coinos-server-7c34b4312c8aafc7643a5192d54daea14cfc1559.zip
ln/lightning: watchdog recycles zombie receive-listener socket
Port of master bd1ece3 to staging. When cl restarts (e.g. autoheal after a healthcheck timeout), the app's waitanyinvoice long-poll can hang on the now-dead listen socket: listenerActive stays true forever, nothing restarts it, and incoming lightning payments silently stop crediting until a manual app restart. The per-call RPC timeout can't catch this — waitanyinvoice is meant to block. ensureListenerAlive (run every 120s) now also detects a stalled listener — active but blocked in waitanyinvoice for >5min — probes cl via the main socket (getinfo), and only if cl is actually alive treats the listen socket as a zombie: bumps a listenerEpoch, calls lnListen.reset() (new: drops the proxy socket so the next call reconnects), and re-arms. The epoch guard makes the wedged invocation bow out when its waitanyinvoice finally rejects, so we never run two listeners or double-credit. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'index.ts')
-rw-r--r--index.ts3
1 files changed, 2 insertions, 1 deletions
diff --git a/index.ts b/index.ts
index a664638d..98a9668e 100644
--- a/index.ts
+++ b/index.ts
@@ -5,7 +5,7 @@ import { admin, auth, optional } from "$lib/auth";
import { getDelegateInfo, receiveDelegation } from "$lib/delegator";
import { g, s } from "$lib/db";
-import { fixBolt12, listenForLightning, replay } from "$lib/lightning";
+import { ensureListenerAlive, fixBolt12, listenForLightning, replay } from "$lib/lightning";
import { l } from "$lib/logging";
import { startHealthCheck } from "$lib/health";
import { getLocations } from "$lib/locations";
@@ -49,6 +49,7 @@ setTimeout(listenForLightning, 2000);
listenForDMs();
initMlsIndex();
setInterval(sendHeartbeat, 2000);
+setInterval(ensureListenerAlive, 120_000); // LN listener watchdog
app.get("/balances", info.balances);
app.get("/health", info.health);