|
|
|
|
@ -79,20 +79,28 @@ export async function fetchNostrEvent(filter: NostrFilter): Promise<NostrEvent |
@@ -79,20 +79,28 @@ export async function fetchNostrEvent(filter: NostrFilter): Promise<NostrEvent |
|
|
|
|
|
const outboxRelays = get(activeOutboxRelays); |
|
|
|
|
|
|
|
|
|
// Combine all available relays, prioritizing inbox relays
|
|
|
|
|
const availableRelays = [...inboxRelays, ...outboxRelays]; |
|
|
|
|
let availableRelays = [...inboxRelays, ...outboxRelays]; |
|
|
|
|
|
|
|
|
|
// AI-NOTE: Use fallback relays when stores are empty (e.g., during SSR)
|
|
|
|
|
// This ensures publications can still load even when relay stores haven't been populated
|
|
|
|
|
if (availableRelays.length === 0) { |
|
|
|
|
// AI-NOTE: Return null instead of throwing error when no relays are available
|
|
|
|
|
// This allows the publication routes to handle the case gracefully during preloading
|
|
|
|
|
// when relay stores haven't been populated yet
|
|
|
|
|
console.warn("[WebSocket Utils]: No relays available for fetching events, returning null"); |
|
|
|
|
return null; |
|
|
|
|
console.warn("[WebSocket Utils]: No relays in stores, using fallback relays"); |
|
|
|
|
// Import fallback relays from constants
|
|
|
|
|
const { searchRelays, secondaryRelays } = await import("../consts.ts"); |
|
|
|
|
availableRelays = [...searchRelays, ...secondaryRelays]; |
|
|
|
|
|
|
|
|
|
if (availableRelays.length === 0) { |
|
|
|
|
console.warn("[WebSocket Utils]: No fallback relays available, using thecitadel.nostr1.com as final fallback"); |
|
|
|
|
availableRelays = ["wss://thecitadel.nostr1.com"]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Select a relay - prefer inbox relays if available, otherwise use any available relay
|
|
|
|
|
const selectedRelay = inboxRelays.length > 0 ? inboxRelays[0] : availableRelays[0]; |
|
|
|
|
// Try all available relays in parallel and return the first result
|
|
|
|
|
const relayPromises = availableRelays.map(async (relay) => { |
|
|
|
|
try { |
|
|
|
|
console.debug(`[WebSocket Utils]: Trying relay: ${relay}`); |
|
|
|
|
|
|
|
|
|
const ws = await WebSocketPool.instance.acquire(selectedRelay); |
|
|
|
|
const ws = await WebSocketPool.instance.acquire(relay); |
|
|
|
|
const subId = crypto.randomUUID(); |
|
|
|
|
|
|
|
|
|
// AI-NOTE: Currying is used here to abstract the internal handler logic away from the WebSocket
|
|
|
|
|
@ -129,7 +137,48 @@ export async function fetchNostrEvent(filter: NostrFilter): Promise<NostrEvent |
@@ -129,7 +137,48 @@ export async function fetchNostrEvent(filter: NostrFilter): Promise<NostrEvent |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
ws.send(JSON.stringify(["REQ", subId, filter])); |
|
|
|
|
return res; |
|
|
|
|
|
|
|
|
|
const result = await res; |
|
|
|
|
if (result) { |
|
|
|
|
console.debug(`[WebSocket Utils]: Found event on relay: ${relay}`); |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
console.debug(`[WebSocket Utils]: No event found on relay: ${relay}`); |
|
|
|
|
return null; |
|
|
|
|
} catch (err) { |
|
|
|
|
console.warn(`[WebSocket Utils]: Failed to fetch from relay ${relay}:`, err); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Wait for the first successful result or all to fail with timeout
|
|
|
|
|
const timeoutPromise = new Promise<null>((resolve) => { |
|
|
|
|
setTimeout(() => { |
|
|
|
|
console.warn("[WebSocket Utils]: Fetch timeout reached"); |
|
|
|
|
resolve(null); |
|
|
|
|
}, 5000); // 5 second timeout for the entire fetch operation
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const fetchPromise = Promise.allSettled(relayPromises).then((results) => { |
|
|
|
|
// Find the first successful result
|
|
|
|
|
for (const result of results) { |
|
|
|
|
if (result.status === 'fulfilled' && result.value) { |
|
|
|
|
return result.value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Race between the fetch and the timeout
|
|
|
|
|
const result = await Promise.race([fetchPromise, timeoutPromise]); |
|
|
|
|
|
|
|
|
|
if (result) { |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
console.warn("[WebSocket Utils]: Failed to fetch event from all relays (timeout or no results)"); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|