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:
parent
ea72623cde
commit
b6521c4788
2 changed files with 41 additions and 0 deletions
|
|
@ -116,6 +116,12 @@ export function useAvailabilityBroadcast(options: UseAvailabilityBroadcastOption
|
||||||
// Publish immediately on setup
|
// Publish immediately on setup
|
||||||
publish(computeSnapshot())
|
publish(computeSnapshot())
|
||||||
|
|
||||||
|
// Re-publish immediately when relay reconnects (don't wait for next heartbeat)
|
||||||
|
nostrClient.on('connect', () => {
|
||||||
|
console.log('[Availability] Relay reconnected, publishing immediately')
|
||||||
|
publish(computeSnapshot())
|
||||||
|
})
|
||||||
|
|
||||||
function stop() {
|
function stop() {
|
||||||
clearInterval(heartbeatInterval)
|
clearInterval(heartbeatInterval)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 })
|
this.emitEvent('connect', { relay: url })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
connection.state = '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
|
* Schedule a reconnection attempt
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue