diff --git a/apps/machine/src/composables/useAvailabilityBroadcast.ts b/apps/machine/src/composables/useAvailabilityBroadcast.ts index 1fc2189..fa7bdd9 100644 --- a/apps/machine/src/composables/useAvailabilityBroadcast.ts +++ b/apps/machine/src/composables/useAvailabilityBroadcast.ts @@ -116,6 +116,12 @@ export function useAvailabilityBroadcast(options: UseAvailabilityBroadcastOption // Publish immediately on setup 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() { clearInterval(heartbeatInterval) } diff --git a/packages/nostr-client/src/client.ts b/packages/nostr-client/src/client.ts index 58837df..0d35b4d 100644 --- a/packages/nostr-client/src/client.ts +++ b/packages/nostr-client/src/client.ts @@ -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 */