Speed up profile loading

This commit is contained in:
Jon Staab
2024-09-10 09:51:03 -07:00
parent 77e8243d8b
commit bece689530
7 changed files with 44 additions and 22 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
import {FOLLOWS, asDecryptedEvent, readList} from '@welshman/util' import {FOLLOWS, asDecryptedEvent, readList} from '@welshman/util'
import {type TrustedEvent, type PublishedList} from '@welshman/util' import {type TrustedEvent, type PublishedList} from '@welshman/util'
import {type SubscribeRequest} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {deriveEventsMapped, withGetter} from '@welshman/store' import {deriveEventsMapped, withGetter} from '@welshman/store'
import {repository, load} from './core' import {repository, load} from './core'
import {collection} from './collection' import {collection} from './collection'
@@ -28,7 +28,7 @@ export const {
name: "follows", name: "follows",
store: follows, store: follows,
getKey: follows => follows.event.pubkey, getKey: follows => follows.event.pubkey,
load: async (pubkey: string, request: Partial<SubscribeRequest> = {}) => { load: async (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) => {
await loadRelaySelections(pubkey, request) await loadRelaySelections(pubkey, request)
await load({...request, filters: [{kinds: [FOLLOWS], authors: [pubkey]}]}) await load({...request, filters: [{kinds: [FOLLOWS], authors: [pubkey]}]})
}, },
+2 -2
View File
@@ -1,6 +1,6 @@
import {writable, derived} from 'svelte/store' import {writable, derived} from 'svelte/store'
import {withGetter} from '@welshman/store' import {withGetter} from '@welshman/store'
import {type SubscribeRequest} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {ctx, tryCatch, fetchJson, uniq, batcher, postJson, last} from '@welshman/lib' import {ctx, tryCatch, fetchJson, uniq, batcher, postJson, last} from '@welshman/lib'
import {collection} from './collection' import {collection} from './collection'
import {deriveProfile} from './profiles' import {deriveProfile} from './profiles'
@@ -97,7 +97,7 @@ export const {
}), }),
}) })
export const deriveHandleForPubkey = (pubkey: string, request: Partial<SubscribeRequest> = {}) => export const deriveHandleForPubkey = (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) =>
derived( derived(
[handlesByNip05, deriveProfile(pubkey, request)], [handlesByNip05, deriveProfile(pubkey, request)],
([$handlesByNip05, $profile]) => { ([$handlesByNip05, $profile]) => {
+2 -2
View File
@@ -1,6 +1,6 @@
import {MUTES, asDecryptedEvent, readList} from '@welshman/util' import {MUTES, asDecryptedEvent, readList} from '@welshman/util'
import {type TrustedEvent, type PublishedList} from '@welshman/util' import {type TrustedEvent, type PublishedList} from '@welshman/util'
import {type SubscribeRequest} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {deriveEventsMapped, withGetter} from '@welshman/store' import {deriveEventsMapped, withGetter} from '@welshman/store'
import {repository, load} from './core' import {repository, load} from './core'
import {collection} from './collection' import {collection} from './collection'
@@ -28,7 +28,7 @@ export const {
name: "mutes", name: "mutes",
store: mutes, store: mutes,
getKey: mute => mute.event.pubkey, getKey: mute => mute.event.pubkey,
load: async (pubkey: string, request: Partial<SubscribeRequest> = {}) => { load: async (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) => {
await loadRelaySelections(pubkey, request) await loadRelaySelections(pubkey, request)
await load({...request, filters: [{kinds: [MUTES], authors: [pubkey]}]}) await load({...request, filters: [{kinds: [MUTES], authors: [pubkey]}]})
}, },
+20 -5
View File
@@ -1,7 +1,7 @@
import {derived, readable} from 'svelte/store' import {derived, readable} from 'svelte/store'
import {readProfile, displayProfile, displayPubkey, PROFILE} from '@welshman/util' import {readProfile, displayProfile, displayPubkey, PROFILE} from '@welshman/util'
import {type SubscribeRequest} from "@welshman/net" import type {SubscribeRequestWithHandlers} from "@welshman/net"
import {type PublishedProfile} from "@welshman/util" import type {PublishedProfile, TrustedEvent} from "@welshman/util"
import {deriveEventsMapped, withGetter} from '@welshman/store' import {deriveEventsMapped, withGetter} from '@welshman/store'
import {repository, load} from './core' import {repository, load} from './core'
import {createSearch} from './util' import {createSearch} from './util'
@@ -24,9 +24,24 @@ export const {
name: "profiles", name: "profiles",
store: profiles, store: profiles,
getKey: profile => profile.event.pubkey, getKey: profile => profile.event.pubkey,
load: async (pubkey: string, request: Partial<SubscribeRequest> = {}) => { load: async (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) => {
await loadRelaySelections(pubkey, request) const filters = [{kinds: [PROFILE], authors: [pubkey]}]
await load({...request, filters: [{kinds: [PROFILE], authors: [pubkey]}]})
// Attempt to load the user profile right away, regardless of whether we have relays,
// since profiles are crucial to UX
load({...request, filters})
// Load relay selections as quickly as possible, moving on to retrying profiles with
// better selections the moment we have a result, even if it's outdated
await new Promise<void>(resolve => {
loadRelaySelections(pubkey, {
onEvent: (event: TrustedEvent) => {
resolve()
}
})
})
await load({...request, filters})
}, },
}) })
+3 -3
View File
@@ -1,5 +1,5 @@
import {INBOX_RELAYS, RELAYS, getRelayTags, normalizeRelayUrl, type TrustedEvent} from '@welshman/util' import {INBOX_RELAYS, RELAYS, getRelayTags, normalizeRelayUrl, type TrustedEvent} from '@welshman/util'
import {type SubscribeRequest} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {deriveEvents, withGetter} from '@welshman/store' import {deriveEvents, withGetter} from '@welshman/store'
import {load, repository} from './core' import {load, repository} from './core'
import {collection} from './collection' import {collection} from './collection'
@@ -28,7 +28,7 @@ export const {
name: "relaySelections", name: "relaySelections",
store: relaySelections, store: relaySelections,
getKey: relaySelections => relaySelections.pubkey, getKey: relaySelections => relaySelections.pubkey,
load: (pubkey: string, request: Partial<SubscribeRequest> = {}) => load: (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) =>
load({...request, filters: [{kinds: [RELAYS], authors: [pubkey]}]}), load({...request, filters: [{kinds: [RELAYS], authors: [pubkey]}]}),
}) })
@@ -42,6 +42,6 @@ export const {
name: "inboxRelaySelections", name: "inboxRelaySelections",
store: inboxRelaySelections, store: inboxRelaySelections,
getKey: inboxRelaySelections => inboxRelaySelections.pubkey, getKey: inboxRelaySelections => inboxRelaySelections.pubkey,
load: (pubkey: string, request: Partial<SubscribeRequest> = {}) => load: (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) =>
load({...request, filters: [{kinds: [INBOX_RELAYS], authors: [pubkey]}]}), load({...request, filters: [{kinds: [INBOX_RELAYS], authors: [pubkey]}]}),
}) })
+8 -5
View File
@@ -1,7 +1,7 @@
import {writable, derived} from 'svelte/store' import {writable, derived} from 'svelte/store'
import {withGetter} from '@welshman/store' import {withGetter} from '@welshman/store'
import {type Zapper} from '@welshman/util' import {type Zapper} from '@welshman/util'
import {type SubscribeRequest} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {ctx, identity, fetchJson, uniq, bech32ToHex, hexToBech32, tryCatch, batcher, postJson} from '@welshman/lib' import {ctx, identity, fetchJson, uniq, bech32ToHex, hexToBech32, tryCatch, batcher, postJson} from '@welshman/lib'
import {collection} from './collection' import {collection} from './collection'
import {deriveProfile} from './profiles' import {deriveProfile} from './profiles'
@@ -15,10 +15,13 @@ export const fetchZappers = async (lnurls: string[]) => {
// Use dufflepud if we it's set up to protect user privacy, otherwise fetch directly // Use dufflepud if we it's set up to protect user privacy, otherwise fetch directly
if (base) { if (base) {
const hexUrls = lnurls.map(lnurl => tryCatch(() => bech32ToHex(lnurl))).filter(identity) const hexUrls = lnurls.map(lnurl => tryCatch(() => bech32ToHex(lnurl))).filter(identity)
const res: any = await tryCatch(async () => await postJson(`${base}/zapper/info`, {lnurls: hexUrls}))
for (const {lnurl, info} of res?.data || []) { if (hexUrls.length > 0) {
tryCatch(() => zappersByLnurl.set(hexToBech32("lnurl", lnurl), info)) const res: any = await tryCatch(async () => await postJson(`${base}/zapper/info`, {lnurls: hexUrls}))
for (const {lnurl, info} of res?.data || []) {
tryCatch(() => zappersByLnurl.set(hexToBech32("lnurl", lnurl), info))
}
} }
} else { } else {
const results = await Promise.all( const results = await Promise.all(
@@ -68,7 +71,7 @@ export const {
}), }),
}) })
export const deriveZapperForPubkey = (pubkey: string, request: Partial<SubscribeRequest> = {}) => export const deriveZapperForPubkey = (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) =>
derived( derived(
[zappersByLnurl, deriveProfile(pubkey, request)], [zappersByLnurl, deriveProfile(pubkey, request)],
([$zappersByLnurl, $profile]) => { ([$zappersByLnurl, $profile]) => {
+7 -3
View File
@@ -139,7 +139,8 @@ export const optimizeSubscriptions = (subs: Subscription[]) => {
const mergedSubs = [] const mergedSubs = []
for (const {relays, filters} of ctx.net.optimizeSubscriptions(group)) { for (const {relays, filters} of ctx.net.optimizeSubscriptions(group)) {
const mergedSub = makeSubscription({filters, const mergedSub = makeSubscription({
filters,
relays, relays,
timeout, timeout,
authTimeout, authTimeout,
@@ -211,7 +212,7 @@ export const optimizeSubscriptions = (subs: Subscription[]) => {
}) })
} }
export const executeSubscription = (sub: Subscription) => { const _executeSubscription = (sub: Subscription) => {
const {request, emitter, tracker, controller} = sub const {request, emitter, tracker, controller} = sub
const {filters, closeOnEose, relays, signal, timeout, authTimeout = 0} = request const {filters, closeOnEose, relays, signal, timeout, authTimeout = 0} = request
const executor = ctx.net.getExecutor(relays) const executor = ctx.net.getExecutor(relays)
@@ -305,8 +306,11 @@ export const executeSubscription = (sub: Subscription) => {
} }
} }
export const executeSubscription = (sub: Subscription) =>
optimizeSubscriptions([sub]).forEach(_executeSubscription)
export const executeSubscriptions = (subs: Subscription[]) => export const executeSubscriptions = (subs: Subscription[]) =>
optimizeSubscriptions(subs).forEach(executeSubscription) optimizeSubscriptions(subs).forEach(_executeSubscription)
export const executeSubscriptionBatched = (() => { export const executeSubscriptionBatched = (() => {
const subs: Subscription[] = [] const subs: Subscription[] = []