feat: require success on one-third of relays to consider publish successful
This commit is contained in:
@@ -149,12 +149,14 @@ export default function PostContent({
|
|||||||
addReplies([newEvent])
|
addReplies([newEvent])
|
||||||
close()
|
close()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof AggregateError) {
|
const errors = error instanceof AggregateError ? error.errors : [error]
|
||||||
error.errors.forEach((e) => toast.error(`${t('Failed to post')}: ${e.message}`))
|
errors.forEach((err) => {
|
||||||
} else if (error instanceof Error) {
|
toast.error(
|
||||||
toast.error(`${t('Failed to post')}: ${error.message}`)
|
`${t('Failed to post')}: ${err instanceof Error ? err.message : String(err)}`,
|
||||||
}
|
{ duration: 10_000 }
|
||||||
console.error(error)
|
)
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
return
|
return
|
||||||
} finally {
|
} finally {
|
||||||
setPosting(false)
|
setPosting(false)
|
||||||
|
|||||||
@@ -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))
|
||||||
const result = await Promise.any(
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user