Browse Source

make relays more efficient

imwald
Silberengel 5 months ago
parent
commit
1df2e61f78
  1. 8
      src/components/QuoteList/index.tsx
  2. 10
      src/components/ReplyNoteList/index.tsx
  3. 16
      src/constants.ts
  4. 27
      src/services/client.service.ts

8
src/components/QuoteList/index.tsx

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
import { FAST_READ_RELAY_URLS, ExtendedKind } from '@/constants'
import { getReplaceableCoordinateFromEvent, isReplaceableEvent } from '@/lib/event'
import { useNostr } from '@/providers/NostrProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
@ -32,14 +32,16 @@ export default function QuoteList({ event, className }: { event: Event; classNam @@ -32,14 +32,16 @@ export default function QuoteList({ event, className }: { event: Event; classNam
const relayList = await client.fetchRelayList(event.pubkey)
// Include user's mailbox relays for better quote discovery
const userRelays = userRelayList?.read || []
const relayUrls = relayList.read.concat(userRelays).concat(BIG_RELAY_URLS)
const relayUrls = Array.from(new Set(relayList.read.concat(userRelays).concat(FAST_READ_RELAY_URLS)))
const seenOn = client.getSeenEventRelayUrls(event.id)
relayUrls.unshift(...seenOn)
// Deduplicate the final list including seenOn relays
const finalRelayUrls = Array.from(new Set(relayUrls))
const { closer, timelineKey } = await client.subscribeTimeline(
[
{
urls: relayUrls,
urls: finalRelayUrls,
filter: {
'#q': [
isReplaceableEvent(event.kind) ? getReplaceableCoordinateFromEvent(event) : event.id

10
src/components/ReplyNoteList/index.tsx

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
import { FAST_READ_RELAY_URLS, ExtendedKind } from '@/constants'
import {
getParentETag,
getReplaceableCoordinateFromEvent,
@ -145,7 +145,7 @@ export default function ReplyNoteList({ index, event }: { index?: number; event: @@ -145,7 +145,7 @@ export default function ReplyNoteList({ index, event }: { index?: number; event:
)
// Include user's mailbox relays for better reply discovery
const userRelays = userRelayList?.read || []
const relayUrls = relayList.read.concat(userRelays).concat(BIG_RELAY_URLS)
const relayUrls = Array.from(new Set(relayList.read.concat(userRelays).concat(FAST_READ_RELAY_URLS)))
const seenOn =
rootInfo.type === 'E'
? client.getSeenEventRelayUrls(rootInfo.id)
@ -153,6 +153,8 @@ export default function ReplyNoteList({ index, event }: { index?: number; event: @@ -153,6 +153,8 @@ export default function ReplyNoteList({ index, event }: { index?: number; event:
? client.getSeenEventRelayUrls(rootInfo.eventId)
: []
relayUrls.unshift(...seenOn)
// Deduplicate the final list including seenOn relays
const finalRelayUrls = Array.from(new Set(relayUrls))
const filters: (Omit<Filter, 'since' | 'until'> & {
limit: number
@ -184,7 +186,7 @@ export default function ReplyNoteList({ index, event }: { index?: number; event: @@ -184,7 +186,7 @@ export default function ReplyNoteList({ index, event }: { index?: number; event:
}
)
if (rootInfo.relay) {
relayUrls.push(rootInfo.relay)
finalRelayUrls.push(rootInfo.relay)
}
} else {
filters.push({
@ -195,7 +197,7 @@ export default function ReplyNoteList({ index, event }: { index?: number; event: @@ -195,7 +197,7 @@ export default function ReplyNoteList({ index, event }: { index?: number; event:
}
const { closer, timelineKey } = await client.subscribeTimeline(
filters.map((filter) => ({
urls: relayUrls.slice(0, 5),
urls: finalRelayUrls.slice(0, 5),
filter
})),
{

16
src/constants.ts

@ -67,6 +67,22 @@ export const BIG_RELAY_URLS = [ @@ -67,6 +67,22 @@ export const BIG_RELAY_URLS = [
'wss://nostr21.com'
]
// Optimized relay list for read operations (includes aggregator)
export const FAST_READ_RELAY_URLS = [
'wss://theforest.nostr1.com',
'wss://orly-relay.imwald.eu',
'wss://nostr.wine',
'wss://aggr.nostr.land'
]
// Optimized relay list for write operations (no aggregator since it's read-only)
export const FAST_WRITE_RELAY_URLS = [
'wss://nostr.wine',
'wss://nostr.land',
'wss://freelay.sovbit.host/',
'wss://thecitadel.nostr1.com/'
]
export const SEARCHABLE_RELAY_URLS = ['wss://relay.nostr.band/', 'wss://freelay.sovbit.host/', 'wss://relay.damus.io/', 'wss://search.nos.today/', 'wss://aggr.nostr.land', 'wss://purplepag.es', 'wss://profiles.nostr1.com']
// Combined relay URLs for profile fetching - includes both BIG_RELAY_URLS and SEARCHABLE_RELAY_URLS

27
src/services/client.service.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { BIG_RELAY_URLS, ExtendedKind, PROFILE_FETCH_RELAY_URLS } from '@/constants'
import { BIG_RELAY_URLS, ExtendedKind, FAST_READ_RELAY_URLS, FAST_WRITE_RELAY_URLS, PROFILE_FETCH_RELAY_URLS } from '@/constants'
import {
compareEvents,
getReplaceableCoordinate,
@ -131,20 +131,20 @@ class ClientService extends EventTarget { @@ -131,20 +131,20 @@ class ClientService extends EventTarget {
}
const relayList = await this.fetchRelayList(event.pubkey)
relays = (relayList?.write.slice(0, 10) ?? []).concat(
relays = (relayList?.write.slice(0, 6) ?? []).concat(
Array.from(new Set(_additionalRelayUrls)) ?? []
)
}
if (!relays.length) {
relays.push(...BIG_RELAY_URLS)
relays.push(...FAST_WRITE_RELAY_URLS)
}
return relays
}
async publishEvent(relayUrls: string[], event: NEvent) {
const uniqueRelayUrls = Array.from(new Set(relayUrls))
const uniqueRelayUrls = this.optimizeRelaySelection(Array.from(new Set(relayUrls)))
await new Promise<void>((resolve, reject) => {
let successCount = 0
let finishedCount = 0
@ -154,7 +154,7 @@ class ClientService extends EventTarget { @@ -154,7 +154,7 @@ class ClientService extends EventTarget {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const that = this
const relay = await this.pool.ensureRelay(url)
relay.publishTimeout = 10_000 // 10s
relay.publishTimeout = 8_000 // 8s
return relay
.publish(event)
.then(() => {
@ -367,7 +367,7 @@ class ClientService extends EventTarget { @@ -367,7 +367,7 @@ class ClientService extends EventTarget {
onAllClose?: (reasons: string[]) => void
}
) {
const relays = Array.from(new Set(urls))
const relays = this.optimizeRelaySelection(Array.from(new Set(urls)))
const filters = Array.isArray(filter) ? filter : [filter]
// eslint-disable-next-line @typescript-eslint/no-this-alias
@ -386,7 +386,7 @@ class ClientService extends EventTarget { @@ -386,7 +386,7 @@ class ClientService extends EventTarget {
async function startSub() {
startedCount++
const relay = await that.pool.ensureRelay(url, { connectionTimeout: 5000 }).catch(() => {
const relay = await that.pool.ensureRelay(url, { connectionTimeout: 3000 }).catch(() => {
return undefined
})
// cannot connect to relay
@ -465,7 +465,7 @@ class ClientService extends EventTarget { @@ -465,7 +465,7 @@ class ClientService extends EventTarget {
}
return
},
eoseTimeout: 10_000 // 10s
eoseTimeout: 8_000 // 8s
})
}
})
@ -657,7 +657,7 @@ class ClientService extends EventTarget { @@ -657,7 +657,7 @@ class ClientService extends EventTarget {
}
getSeenEventRelayUrls(eventId: string) {
return this.getSeenEventRelays(eventId).map((relay) => relay.url)
return Array.from(new Set(this.getSeenEventRelays(eventId).map((relay) => relay.url)))
}
getEventHints(eventId: string) {
@ -875,7 +875,7 @@ class ClientService extends EventTarget { @@ -875,7 +875,7 @@ class ClientService extends EventTarget {
}
private async fetchEventsFromBigRelays(ids: readonly string[]) {
const events = await this.query(PROFILE_FETCH_RELAY_URLS, {
const events = await this.query(FAST_READ_RELAY_URLS, {
ids: Array.from(new Set(ids)),
limit: ids.length
})
@ -1340,6 +1340,13 @@ class ClientService extends EventTarget { @@ -1340,6 +1340,13 @@ class ClientService extends EventTarget {
return await this.replaceableEventDataLoader.loadMany(params)
}
// ================= Performance Optimization =================
private optimizeRelaySelection(relays: string[]): string[] {
// Limit to 4 relays for better performance
return relays.slice(0, 4)
}
// ================= Utils =================
async generateSubRequestsForPubkeys(pubkeys: string[], myPubkey?: string | null) {

Loading…
Cancel
Save