Compare commits
No commits in common. "fb1c239e152c2db8ce567afe495e1461ce49ce6d" and "662dd21a60acbd4ae12225af2736b4c2cd6fc8be" have entirely different histories.
fb1c239e15
...
662dd21a60
1 changed files with 42 additions and 50 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import "websocket-polyfill";
|
import "websocket-polyfill";
|
||||||
import NDK, { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKRpcRequest, NDKRpcResponse, NDKUser } from '@nostr-dev-kit/ndk';
|
import NDK, { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKRpcRequest, NDKRpcResponse, NDKUser, NostrEvent } from '@nostr-dev-kit/ndk';
|
||||||
import { NDKNostrRpc } from '@nostr-dev-kit/ndk';
|
import { NDKNostrRpc } from '@nostr-dev-kit/ndk';
|
||||||
import createDebug from 'debug';
|
import createDebug from 'debug';
|
||||||
import { Key, KeyUser } from '../run';
|
import { Key, KeyUser } from '../run';
|
||||||
|
|
@ -168,17 +168,12 @@ class AdminInterface {
|
||||||
this.handleRequest(req);
|
this.handleRequest(req);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Connection watchdog: exit if pool reports no connected relays
|
// pingOrDie disabled — NDK 2.8.1 outbox model doesn't echo
|
||||||
// for >60s so the process supervisor (systemd / docker restart
|
// self-published events back through subscriptions on
|
||||||
// policy / k8s) can recover. Replaces the original self-echo
|
// non-public relay channels, so the watchdog fires false
|
||||||
// pingOrDie — see relayConnectionWatchdog comment + #4 + #7.
|
// positives and exits the bunker every 50s on private relays.
|
||||||
// Operators with external liveness checking can disable via
|
// See aiolabs/nsecbunkerd#4 + #7.
|
||||||
// NSEC_BUNKER_DISABLE_WATCHDOG=1.
|
// pingOrDie(this.ndk);
|
||||||
if (process.env.NSEC_BUNKER_DISABLE_WATCHDOG !== '1') {
|
|
||||||
relayConnectionWatchdog(this.ndk);
|
|
||||||
} else {
|
|
||||||
console.log('⏸ watchdog disabled via NSEC_BUNKER_DISABLE_WATCHDOG=1');
|
|
||||||
}
|
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.log('❌ admin connection failed');
|
console.log('❌ admin connection failed');
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|
@ -459,47 +454,44 @@ class AdminInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async function pingOrDie(ndk: NDK) {
|
||||||
* Pool-status connection watchdog. Exits the daemon if every relay in
|
let deathTimer: NodeJS.Timeout | null = null;
|
||||||
* the pool stays disconnected for longer than PARTITION_THRESHOLD_MS.
|
|
||||||
*
|
function resetDeath() {
|
||||||
* Replaces the original `pingOrDie` self-echo watchdog, which published
|
if (deathTimer) clearTimeout(deathTimer);
|
||||||
* a kind-24133 event to its own pubkey every 20s and exited if it
|
deathTimer = setTimeout(() => {
|
||||||
* didn't see the echo within 50s. That works on public relays but
|
console.log(`❌ No ping event received in 30 seconds. Exiting.`);
|
||||||
* silently breaks on single-private-relay setups: NDK 2.8.1's outbox
|
process.exit(1);
|
||||||
* model doesn't reliably route self-publishes back through the
|
}, 50000);
|
||||||
* matching subscription, so the watchdog fires false positives and
|
}
|
||||||
* exits the daemon every 50s while RPCs over the same channel still
|
|
||||||
* work fine. See aiolabs/nsecbunkerd#4 + #7.
|
const self = await ndk.signer!.user();
|
||||||
*
|
const sub = ndk.subscribe({
|
||||||
* The pool-status approach uses NDK's own connection-lifecycle
|
authors: [self.pubkey],
|
||||||
* tracking — `pool.connectedRelays()` reports relays in
|
kinds: [NDKKind.NostrConnect],
|
||||||
* NDKRelayStatus.CONNECTED — which is reliable across all relay
|
"#p": [self.pubkey]
|
||||||
* configurations because it doesn't depend on round-trip
|
});
|
||||||
* publish/subscribe. No event is published; no relay traffic.
|
sub.on("event", (event: NDKEvent) => {
|
||||||
*
|
console.log(`🔔 Received ping event:`, event.created_at);
|
||||||
* Detects partition within POLL_INTERVAL + PARTITION_THRESHOLD ms.
|
resetDeath();
|
||||||
* Transient disconnects shorter than PARTITION_THRESHOLD don't trip
|
});
|
||||||
* the watchdog — useful for relays that flap or briefly drop on
|
sub.start();
|
||||||
* network blips.
|
|
||||||
*/
|
resetDeath();
|
||||||
async function relayConnectionWatchdog(ndk: NDK) {
|
|
||||||
const POLL_INTERVAL_MS = 10_000;
|
|
||||||
const PARTITION_THRESHOLD_MS = 60_000;
|
|
||||||
let lastConnectedAt = Date.now();
|
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const connectedCount = ndk.pool.connectedRelays().length;
|
const event = new NDKEvent(ndk, {
|
||||||
if (connectedCount > 0) {
|
kind: NDKKind.NostrConnect,
|
||||||
lastConnectedAt = Date.now();
|
tags: [ ["p", self.pubkey] ],
|
||||||
return;
|
content: "ping"
|
||||||
}
|
} as NostrEvent);
|
||||||
const elapsed = Date.now() - lastConnectedAt;
|
event.publish().then(() => {
|
||||||
if (elapsed > PARTITION_THRESHOLD_MS) {
|
console.log(`🔔 Sent ping event:`, event.created_at);
|
||||||
console.log(`❌ No connected relays for ${Math.floor(elapsed / 1000)}s. Exiting.`);
|
}).catch((e: any) => {
|
||||||
|
console.log(`❌ Failed to send ping event:`, e.message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
});
|
||||||
}, POLL_INTERVAL_MS);
|
}, 20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AdminInterface;
|
export default AdminInterface;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue