|
|
|
@ -178,14 +178,14 @@ class ClientService extends EventTarget { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async publishEvent(relayUrls: string[], event: NEvent) { |
|
|
|
async publishEvent(relayUrls: string[], event: NEvent) { |
|
|
|
console.log('🔵 [PublishEvent] Starting publishEvent', { |
|
|
|
logger.debug('[PublishEvent] Starting publishEvent', { |
|
|
|
eventId: event.id?.substring(0, 8), |
|
|
|
eventId: event.id?.substring(0, 8), |
|
|
|
kind: event.kind, |
|
|
|
kind: event.kind, |
|
|
|
relayCount: relayUrls.length |
|
|
|
relayCount: relayUrls.length |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
const uniqueRelayUrls = Array.from(new Set(relayUrls)) |
|
|
|
const uniqueRelayUrls = Array.from(new Set(relayUrls)) |
|
|
|
console.log('🔵 [PublishEvent] Unique relays', { count: uniqueRelayUrls.length, relays: uniqueRelayUrls.slice(0, 5) }) |
|
|
|
logger.debug('[PublishEvent] Unique relays', { count: uniqueRelayUrls.length, relays: uniqueRelayUrls.slice(0, 5) }) |
|
|
|
|
|
|
|
|
|
|
|
const relayStatuses: { url: string; success: boolean; error?: string }[] = [] |
|
|
|
const relayStatuses: { url: string; success: boolean; error?: string }[] = [] |
|
|
|
|
|
|
|
|
|
|
|
@ -194,17 +194,17 @@ class ClientService extends EventTarget { |
|
|
|
let finishedCount = 0 |
|
|
|
let finishedCount = 0 |
|
|
|
const errors: { url: string; error: any }[] = [] |
|
|
|
const errors: { url: string; error: any }[] = [] |
|
|
|
|
|
|
|
|
|
|
|
console.log('🔵 [PublishEvent] Setting up global timeout (30 seconds)') |
|
|
|
logger.debug('[PublishEvent] Setting up global timeout (30 seconds)') |
|
|
|
let hasResolved = false |
|
|
|
let hasResolved = false |
|
|
|
|
|
|
|
|
|
|
|
// Add a global timeout to prevent hanging - use 30 seconds for faster feedback
|
|
|
|
// Add a global timeout to prevent hanging - use 30 seconds for faster feedback
|
|
|
|
const globalTimeout = setTimeout(() => { |
|
|
|
const globalTimeout = setTimeout(() => { |
|
|
|
if (hasResolved) { |
|
|
|
if (hasResolved) { |
|
|
|
console.log('🔵 [PublishEvent] Already resolved, ignoring timeout') |
|
|
|
logger.debug('[PublishEvent] Already resolved, ignoring timeout') |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.warn('⚠️ [PublishEvent] Global timeout reached!', { |
|
|
|
logger.warn('[PublishEvent] Global timeout reached!', { |
|
|
|
finishedCount, |
|
|
|
finishedCount, |
|
|
|
totalRelays: uniqueRelayUrls.length, |
|
|
|
totalRelays: uniqueRelayUrls.length, |
|
|
|
successCount, |
|
|
|
successCount, |
|
|
|
@ -215,7 +215,7 @@ class ClientService extends EventTarget { |
|
|
|
uniqueRelayUrls.forEach(url => { |
|
|
|
uniqueRelayUrls.forEach(url => { |
|
|
|
const alreadyFinished = relayStatuses.some(rs => rs.url === url) |
|
|
|
const alreadyFinished = relayStatuses.some(rs => rs.url === url) |
|
|
|
if (!alreadyFinished) { |
|
|
|
if (!alreadyFinished) { |
|
|
|
console.warn('⚠️ [PublishEvent] Marking relay as timed out', { url }) |
|
|
|
logger.warn('[PublishEvent] Marking relay as timed out', { url }) |
|
|
|
relayStatuses.push({ url, success: false, error: 'Timeout: Operation took too long' }) |
|
|
|
relayStatuses.push({ url, success: false, error: 'Timeout: Operation took too long' }) |
|
|
|
finishedCount++ |
|
|
|
finishedCount++ |
|
|
|
} |
|
|
|
} |
|
|
|
@ -224,7 +224,7 @@ class ClientService extends EventTarget { |
|
|
|
// Ensure we resolve even if not all relays finished
|
|
|
|
// Ensure we resolve even if not all relays finished
|
|
|
|
if (!hasResolved) { |
|
|
|
if (!hasResolved) { |
|
|
|
hasResolved = true |
|
|
|
hasResolved = true |
|
|
|
console.log('✅ [PublishEvent] Resolving due to timeout', { |
|
|
|
logger.debug('[PublishEvent] Resolving due to timeout', { |
|
|
|
success: successCount >= uniqueRelayUrls.length / 3, |
|
|
|
success: successCount >= uniqueRelayUrls.length / 3, |
|
|
|
successCount, |
|
|
|
successCount, |
|
|
|
totalCount: uniqueRelayUrls.length, |
|
|
|
totalCount: uniqueRelayUrls.length, |
|
|
|
@ -239,10 +239,10 @@ class ClientService extends EventTarget { |
|
|
|
} |
|
|
|
} |
|
|
|
}, 30_000) // 30 seconds global timeout (reduced from 2 minutes)
|
|
|
|
}, 30_000) // 30 seconds global timeout (reduced from 2 minutes)
|
|
|
|
|
|
|
|
|
|
|
|
console.log('🔵 [PublishEvent] Starting Promise.allSettled for all relays') |
|
|
|
logger.debug('[PublishEvent] Starting Promise.allSettled for all relays') |
|
|
|
Promise.allSettled( |
|
|
|
Promise.allSettled( |
|
|
|
uniqueRelayUrls.map(async (url, index) => { |
|
|
|
uniqueRelayUrls.map(async (url, index) => { |
|
|
|
console.log(`🔵 [PublishEvent] Starting relay ${index + 1}/${uniqueRelayUrls.length}`, { url }) |
|
|
|
logger.debug(`[PublishEvent] Starting relay ${index + 1}/${uniqueRelayUrls.length}`, { url }) |
|
|
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
|
|
const that = this |
|
|
|
const that = this |
|
|
|
const isLocal = isLocalNetworkUrl(url) |
|
|
|
const isLocal = isLocalNetworkUrl(url) |
|
|
|
@ -251,14 +251,14 @@ class ClientService extends EventTarget { |
|
|
|
|
|
|
|
|
|
|
|
// Set up a per-relay timeout to ensure we always reach the finally block
|
|
|
|
// Set up a per-relay timeout to ensure we always reach the finally block
|
|
|
|
const relayTimeout = setTimeout(() => { |
|
|
|
const relayTimeout = setTimeout(() => { |
|
|
|
console.warn(`⚠️ [PublishEvent] Per-relay timeout for ${url}`, { connectionTimeout, publishTimeout }) |
|
|
|
logger.warn(`[PublishEvent] Per-relay timeout for ${url}`, { connectionTimeout, publishTimeout }) |
|
|
|
// This will be caught in the catch block if the promise is still pending
|
|
|
|
// This will be caught in the catch block if the promise is still pending
|
|
|
|
}, connectionTimeout + publishTimeout + 2_000) // Add 2s buffer
|
|
|
|
}, connectionTimeout + publishTimeout + 2_000) // Add 2s buffer
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
// For local relays, add a connection timeout
|
|
|
|
// For local relays, add a connection timeout
|
|
|
|
let relay: Relay |
|
|
|
let relay: Relay |
|
|
|
console.log(`🔵 [PublishEvent] Ensuring relay connection`, { url, isLocal, connectionTimeout }) |
|
|
|
logger.debug(`[PublishEvent] Ensuring relay connection`, { url, isLocal, connectionTimeout }) |
|
|
|
|
|
|
|
|
|
|
|
const connectionPromise = isLocal |
|
|
|
const connectionPromise = isLocal |
|
|
|
? Promise.race([ |
|
|
|
? Promise.race([ |
|
|
|
@ -275,48 +275,48 @@ class ClientService extends EventTarget { |
|
|
|
]) |
|
|
|
]) |
|
|
|
|
|
|
|
|
|
|
|
relay = await connectionPromise |
|
|
|
relay = await connectionPromise |
|
|
|
console.log(`✅ [PublishEvent] Relay connected`, { url }) |
|
|
|
logger.debug(`[PublishEvent] Relay connected`, { url }) |
|
|
|
|
|
|
|
|
|
|
|
relay.publishTimeout = publishTimeout |
|
|
|
relay.publishTimeout = publishTimeout |
|
|
|
|
|
|
|
|
|
|
|
console.log(`🔵 [PublishEvent] Publishing to relay`, { url }) |
|
|
|
logger.debug(`[PublishEvent] Publishing to relay`, { url }) |
|
|
|
|
|
|
|
|
|
|
|
// Wrap publish in a timeout promise
|
|
|
|
// Wrap publish in a timeout promise
|
|
|
|
const publishPromise = relay |
|
|
|
const publishPromise = relay |
|
|
|
.publish(event) |
|
|
|
.publish(event) |
|
|
|
.then(() => { |
|
|
|
.then(() => { |
|
|
|
console.log(`✅ [PublishEvent] Successfully published to relay`, { url }) |
|
|
|
logger.debug(`[PublishEvent] Successfully published to relay`, { url }) |
|
|
|
this.trackEventSeenOn(event.id, relay) |
|
|
|
this.trackEventSeenOn(event.id, relay) |
|
|
|
successCount++ |
|
|
|
successCount++ |
|
|
|
relayStatuses.push({ url, success: true }) |
|
|
|
relayStatuses.push({ url, success: true }) |
|
|
|
}) |
|
|
|
}) |
|
|
|
.catch((error) => { |
|
|
|
.catch((error) => { |
|
|
|
console.warn(`⚠️ [PublishEvent] Publish failed, checking if auth required`, { url, error: error.message }) |
|
|
|
logger.warn(`[PublishEvent] Publish failed, checking if auth required`, { url, error: error.message }) |
|
|
|
if ( |
|
|
|
if ( |
|
|
|
error instanceof Error && |
|
|
|
error instanceof Error && |
|
|
|
error.message.startsWith('auth-required') && |
|
|
|
error.message.startsWith('auth-required') && |
|
|
|
!!that.signer |
|
|
|
!!that.signer |
|
|
|
) { |
|
|
|
) { |
|
|
|
console.log(`🔵 [PublishEvent] Auth required, attempting authentication`, { url }) |
|
|
|
logger.debug(`[PublishEvent] Auth required, attempting authentication`, { url }) |
|
|
|
return relay |
|
|
|
return relay |
|
|
|
.auth((authEvt: EventTemplate) => that.signer!.signEvent(authEvt)) |
|
|
|
.auth((authEvt: EventTemplate) => that.signer!.signEvent(authEvt)) |
|
|
|
.then(() => { |
|
|
|
.then(() => { |
|
|
|
console.log(`✅ [PublishEvent] Auth successful, retrying publish`, { url }) |
|
|
|
logger.debug(`[PublishEvent] Auth successful, retrying publish`, { url }) |
|
|
|
return relay.publish(event) |
|
|
|
return relay.publish(event) |
|
|
|
}) |
|
|
|
}) |
|
|
|
.then(() => { |
|
|
|
.then(() => { |
|
|
|
console.log(`✅ [PublishEvent] Successfully published after auth`, { url }) |
|
|
|
logger.debug(`[PublishEvent] Successfully published after auth`, { url }) |
|
|
|
this.trackEventSeenOn(event.id, relay) |
|
|
|
this.trackEventSeenOn(event.id, relay) |
|
|
|
successCount++ |
|
|
|
successCount++ |
|
|
|
relayStatuses.push({ url, success: true }) |
|
|
|
relayStatuses.push({ url, success: true }) |
|
|
|
}) |
|
|
|
}) |
|
|
|
.catch((authError) => { |
|
|
|
.catch((authError) => { |
|
|
|
console.error(`❌ [PublishEvent] Auth or publish failed`, { url, error: authError.message }) |
|
|
|
logger.error(`[PublishEvent] Auth or publish failed`, { url, error: authError.message }) |
|
|
|
errors.push({ url, error: authError }) |
|
|
|
errors.push({ url, error: authError }) |
|
|
|
relayStatuses.push({ url, success: false, error: authError.message }) |
|
|
|
relayStatuses.push({ url, success: false, error: authError.message }) |
|
|
|
}) |
|
|
|
}) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
console.error(`❌ [PublishEvent] Publish failed`, { url, error: error.message }) |
|
|
|
logger.error(`[PublishEvent] Publish failed`, { url, error: error.message }) |
|
|
|
errors.push({ url, error }) |
|
|
|
errors.push({ url, error }) |
|
|
|
relayStatuses.push({ url, success: false, error: error.message }) |
|
|
|
relayStatuses.push({ url, success: false, error: error.message }) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -330,7 +330,7 @@ class ClientService extends EventTarget { |
|
|
|
) |
|
|
|
) |
|
|
|
]) |
|
|
|
]) |
|
|
|
} catch (error) { |
|
|
|
} catch (error) { |
|
|
|
console.error(`❌ [PublishEvent] Connection or setup failed`, { url, error: error instanceof Error ? error.message : String(error) }) |
|
|
|
logger.error(`[PublishEvent] Connection or setup failed`, { url, error: error instanceof Error ? error.message : String(error) }) |
|
|
|
errors.push({ url, error }) |
|
|
|
errors.push({ url, error }) |
|
|
|
relayStatuses.push({
|
|
|
|
relayStatuses.push({
|
|
|
|
url,
|
|
|
|
url,
|
|
|
|
@ -340,7 +340,7 @@ class ClientService extends EventTarget { |
|
|
|
} finally { |
|
|
|
} finally { |
|
|
|
clearTimeout(relayTimeout) |
|
|
|
clearTimeout(relayTimeout) |
|
|
|
const currentFinished = ++finishedCount |
|
|
|
const currentFinished = ++finishedCount |
|
|
|
console.log(`🔵 [PublishEvent] Relay finished`, {
|
|
|
|
logger.debug(`[PublishEvent] Relay finished`, {
|
|
|
|
url,
|
|
|
|
url,
|
|
|
|
finishedCount: currentFinished,
|
|
|
|
finishedCount: currentFinished,
|
|
|
|
totalRelays: uniqueRelayUrls.length, |
|
|
|
totalRelays: uniqueRelayUrls.length, |
|
|
|
@ -354,7 +354,7 @@ class ClientService extends EventTarget { |
|
|
|
} |
|
|
|
} |
|
|
|
if (currentFinished >= uniqueRelayUrls.length && !hasResolved) { |
|
|
|
if (currentFinished >= uniqueRelayUrls.length && !hasResolved) { |
|
|
|
hasResolved = true |
|
|
|
hasResolved = true |
|
|
|
console.log('✅ [PublishEvent] All relays finished, resolving', { |
|
|
|
logger.debug('[PublishEvent] All relays finished, resolving', { |
|
|
|
success: successCount >= uniqueRelayUrls.length / 3, |
|
|
|
success: successCount >= uniqueRelayUrls.length / 3, |
|
|
|
successCount, |
|
|
|
successCount, |
|
|
|
totalCount: uniqueRelayUrls.length, |
|
|
|
totalCount: uniqueRelayUrls.length, |
|
|
|
@ -376,7 +376,7 @@ class ClientService extends EventTarget { |
|
|
|
setTimeout(() => { |
|
|
|
setTimeout(() => { |
|
|
|
if (!hasResolved) { |
|
|
|
if (!hasResolved) { |
|
|
|
hasResolved = true |
|
|
|
hasResolved = true |
|
|
|
console.log('✅ [PublishEvent] Resolving early with enough successes', { |
|
|
|
logger.debug('[PublishEvent] Resolving early with enough successes', { |
|
|
|
success: true, |
|
|
|
success: true, |
|
|
|
successCount, |
|
|
|
successCount, |
|
|
|
totalCount: uniqueRelayUrls.length, |
|
|
|
totalCount: uniqueRelayUrls.length, |
|
|
|
|