|
|
|
@ -144,9 +144,12 @@ class ClientService extends EventTarget { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async publishEvent(relayUrls: string[], event: NEvent) { |
|
|
|
async publishEvent(relayUrls: string[], event: NEvent) { |
|
|
|
try { |
|
|
|
const uniqueRelayUrls = Array.from(new Set(relayUrls)) |
|
|
|
const uniqueRelayUrls = Array.from(new Set(relayUrls)) |
|
|
|
await new Promise<void>((resolve, reject) => { |
|
|
|
const result = await Promise.any( |
|
|
|
let successCount = 0 |
|
|
|
|
|
|
|
let finishedCount = 0 |
|
|
|
|
|
|
|
const errors: { url: string; error: any }[] = [] |
|
|
|
|
|
|
|
Promise.allSettled( |
|
|
|
uniqueRelayUrls.map(async (url) => { |
|
|
|
uniqueRelayUrls.map(async (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 |
|
|
|
@ -154,6 +157,10 @@ class ClientService extends EventTarget { |
|
|
|
relay.publishTimeout = 10_000 // 10s
|
|
|
|
relay.publishTimeout = 10_000 // 10s
|
|
|
|
return relay |
|
|
|
return relay |
|
|
|
.publish(event) |
|
|
|
.publish(event) |
|
|
|
|
|
|
|
.then(() => { |
|
|
|
|
|
|
|
this.trackEventSeenOn(event.id, relay) |
|
|
|
|
|
|
|
successCount++ |
|
|
|
|
|
|
|
}) |
|
|
|
.catch((error) => { |
|
|
|
.catch((error) => { |
|
|
|
if ( |
|
|
|
if ( |
|
|
|
error instanceof Error && |
|
|
|
error instanceof Error && |
|
|
|
@ -164,23 +171,32 @@ class ClientService extends EventTarget { |
|
|
|
.auth((authEvt: EventTemplate) => that.signer!.signEvent(authEvt)) |
|
|
|
.auth((authEvt: EventTemplate) => that.signer!.signEvent(authEvt)) |
|
|
|
.then(() => relay.publish(event)) |
|
|
|
.then(() => relay.publish(event)) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
throw error |
|
|
|
errors.push({ url, error }) |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
}) |
|
|
|
.then((reason) => { |
|
|
|
.finally(() => { |
|
|
|
this.trackEventSeenOn(event.id, relay) |
|
|
|
// If one third of the relays have accepted the event, consider it a success
|
|
|
|
return reason |
|
|
|
const isSuccess = successCount >= uniqueRelayUrls.length / 3 |
|
|
|
|
|
|
|
if (isSuccess) { |
|
|
|
|
|
|
|
this.emitNewEvent(event) |
|
|
|
|
|
|
|
resolve() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (++finishedCount >= uniqueRelayUrls.length) { |
|
|
|
|
|
|
|
reject( |
|
|
|
|
|
|
|
new AggregateError( |
|
|
|
|
|
|
|
errors.map( |
|
|
|
|
|
|
|
({ url, error }) => |
|
|
|
|
|
|
|
new Error( |
|
|
|
|
|
|
|
`${url}: ${error instanceof Error ? error.message : String(error)}` |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
) |
|
|
|
) |
|
|
|
this.emitNewEvent(event) |
|
|
|
}) |
|
|
|
return result |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
|
|
if (error instanceof AggregateError) { |
|
|
|
|
|
|
|
throw error.errors[0] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
throw error |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
emitNewEvent(event: NEvent) { |
|
|
|
emitNewEvent(event: NEvent) { |
|
|
|
|