fix(nostr-client): restore subscriptions and availability on relay reconnect

When a relay reconnects after a disconnect, all active subscriptions
(including Lightning.Pub RPC listener) are now re-established on the
new relay instance. Previously subscriptions were lost permanently.

Also publishes availability broadcast immediately on reconnect instead
of waiting up to 5 minutes for the next heartbeat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-04-02 20:37:12 -04:00
commit b6521c4788
2 changed files with 41 additions and 0 deletions

View file

@ -116,6 +116,9 @@ export class NostrClient {
}
}
// Re-establish all active subscriptions on the new relay connection
this.resubscribeOnRelay(connection)
this.emitEvent('connect', { relay: url })
} catch (error) {
connection.state = 'error'
@ -175,6 +178,38 @@ export class NostrClient {
})
}
/**
* Re-establish all active subscriptions on a reconnected relay.
* When a relay drops and reconnects, the old Relay instance is gone —
* subscriptions need to be recreated on the new instance.
*/
private resubscribeOnRelay(connection: RelayConnection): void {
if (!connection.relay) return
for (const [id, sub] of this.subscriptions) {
try {
const relaySub = connection.relay.subscribe(sub.filters, {
onevent: (event: Event) => {
sub.options.onEvent(event)
this.emitEvent('event', { relay: connection.config.url, event })
},
oneose: () => {
sub.options.onEose?.()
},
})
// Append to the existing close chain so unsubscribe() cleans up both
const prevClose = sub.close
sub.close = () => {
prevClose()
relaySub.close()
}
console.log(`[Nostr] Restored subscription ${id} on ${connection.config.url}`)
} catch (e) {
console.warn(`[Nostr] Failed to restore subscription ${id} on ${connection.config.url}:`, e)
}
}
}
/**
* Schedule a reconnection attempt
*/