diff --git a/packages/app/src/follows.ts b/packages/app/src/follows.ts index edcd844..5c5cc96 100644 --- a/packages/app/src/follows.ts +++ b/packages/app/src/follows.ts @@ -3,7 +3,7 @@ import {TrustedEvent, PublishedList} from "@welshman/util" import {deriveEventsMapped} from "@welshman/store" import {repository} from "./core.js" import {collection} from "./collection.js" -import {loadWithAsapMetaRelayUrls} from "./relaySelections.js" +import {makeOutboxLoader} from "./relaySelections.js" export const follows = deriveEventsMapped(repository, { filters: [{kinds: [FOLLOWS]}], @@ -19,6 +19,5 @@ export const { name: "follows", store: follows, getKey: follows => follows.event.pubkey, - load: (pubkey: string, relays: string[]) => - loadWithAsapMetaRelayUrls(pubkey, relays, [{kinds: [FOLLOWS], authors: [pubkey]}]), + load: makeOutboxLoader([FOLLOWS]) }) diff --git a/packages/app/src/mutes.ts b/packages/app/src/mutes.ts index f676b83..cddbe57 100644 --- a/packages/app/src/mutes.ts +++ b/packages/app/src/mutes.ts @@ -4,7 +4,7 @@ import {deriveEventsMapped} from "@welshman/store" import {repository} from "./core.js" import {collection} from "./collection.js" import {ensurePlaintext} from "./plaintext.js" -import {loadWithAsapMetaRelayUrls} from "./relaySelections.js" +import {makeOutboxLoader} from "./relaySelections.js" export const mutes = deriveEventsMapped(repository, { filters: [{kinds: [MUTES]}], @@ -25,6 +25,5 @@ export const { name: "mutes", store: mutes, getKey: mute => mute.event.pubkey, - load: (pubkey: string, relays: string[]) => - loadWithAsapMetaRelayUrls(pubkey, relays, [{kinds: [MUTES], authors: [pubkey]}]), + load: makeOutboxLoader([MUTES]) }) diff --git a/packages/app/src/pins.ts b/packages/app/src/pins.ts index 11e802a..9556172 100644 --- a/packages/app/src/pins.ts +++ b/packages/app/src/pins.ts @@ -3,7 +3,7 @@ import {TrustedEvent, PublishedList} from "@welshman/util" import {deriveEventsMapped} from "@welshman/store" import {repository} from "./core.js" import {collection} from "./collection.js" -import {loadWithAsapMetaRelayUrls} from "./relaySelections.js" +import {makeOutboxLoader} from "./relaySelections.js" export const pins = deriveEventsMapped(repository, { filters: [{kinds: [PINS]}], @@ -19,6 +19,5 @@ export const { name: "pins", store: pins, getKey: pins => pins.event.pubkey, - load: (pubkey: string, relays: string[]) => - loadWithAsapMetaRelayUrls(pubkey, relays, [{kinds: [PINS], authors: [pubkey]}]), + load: makeOutboxLoader([PINS]) }) diff --git a/packages/app/src/profiles.ts b/packages/app/src/profiles.ts index e8037cf..aa6b4c1 100644 --- a/packages/app/src/profiles.ts +++ b/packages/app/src/profiles.ts @@ -4,7 +4,7 @@ import {PublishedProfile} from "@welshman/util" import {deriveEventsMapped, withGetter} from "@welshman/store" import {repository} from "./core.js" import {collection} from "./collection.js" -import {loadWithAsapMetaRelayUrls} from "./relaySelections.js" +import {makeOutboxLoader} from "./relaySelections.js" export const profiles = withGetter( deriveEventsMapped(repository, { @@ -22,8 +22,7 @@ export const { name: "profiles", store: profiles, getKey: profile => profile.event.pubkey, - load: (pubkey: string, relays: string[]) => - loadWithAsapMetaRelayUrls(pubkey, relays, [{kinds: [PROFILE], authors: [pubkey]}]), + load: makeOutboxLoader([PROFILE]), }) export const displayProfileByPubkey = (pubkey: string | undefined) => diff --git a/packages/app/src/relaySelections.ts b/packages/app/src/relaySelections.ts index f8cbb14..e2654ba 100644 --- a/packages/app/src/relaySelections.ts +++ b/packages/app/src/relaySelections.ts @@ -1,4 +1,4 @@ -import {uniq} from "@welshman/lib" +import {uniq, batcher, always} from "@welshman/lib" import { INBOX_RELAYS, RELAYS, @@ -10,7 +10,7 @@ import { getRelayTagValues, } from "@welshman/util" import {TrustedEvent, Filter, PublishedList, List} from "@welshman/util" -import {load} from "@welshman/net" +import {request, load, RequestEvent} from "@welshman/net" import {deriveEventsMapped} from "@welshman/store" import {repository} from "./core.js" import {Router} from "./router.js" @@ -33,6 +33,39 @@ export const getWriteRelayUrls = (list?: List): string[] => .map((t: string[]) => normalizeRelayUrl(t[1])), ) + +export type OutboxLoaderRequest = { + pubkey: string + relays: string[] +} + +export const makeOutboxLoader = (kinds: number[]) => { + const loadOutboxRequest = batcher(200, (requests: OutboxLoaderRequest[]) => { + const router = Router.get() + const authors: string[] = [] + const scenarios = [router.Index()] + + for (const {pubkey, relays} of requests) { + authors.push(pubkey) + scenarios.push(router.FromPubkey(pubkey), router.FromRelays(relays)) + } + + const filters = [{authors, kinds}] + const relays = router.merge(scenarios).getUrls() + + const promise = new Promise(resolve => { + const req = request({filters, relays, autoClose: true}) + + req.on(RequestEvent.Eose, () => resolve()) + req.on(RequestEvent.Close, () => resolve()) + }) + + return requests.map(always(promise)) + }) + + return (pubkey: string, relays: string[]) => loadOutboxRequest({pubkey, relays}) +} + export const relaySelections = deriveEventsMapped(repository, { filters: [{kinds: [RELAYS]}], itemToEvent: item => item.event, @@ -47,41 +80,9 @@ export const { name: "relaySelections", store: relaySelections, getKey: relaySelections => relaySelections.event.pubkey, - load: async (pubkey: string, relays: string[]) => { - const router = Router.get() - - await load({ - relays: router - .merge([router.Index(), router.FromRelays(relays), router.FromPubkey(pubkey)]) - .getUrls(), - filters: [{kinds: [RELAYS], authors: [pubkey]}], - }) - }, + load: makeOutboxLoader([RELAYS]), }) -export const loadWithAsapMetaRelayUrls = (pubkey: string, relays: string[], filters: Filter[]) => { - const router = Router.get() - - return new Promise(resolve => { - let resolved = 0 - - const onLoad = (events: TrustedEvent[]) => { - if (++resolved === 2 || events.length > 0) { - resolve(events) - } - } - - load({ - filters, - relays: router.merge([router.Index(), router.FromRelays(relays)]).getUrls(), - }).then(onLoad) - - loadRelaySelections(pubkey, relays) - .then(() => load({filters, relays: router.FromPubkey(pubkey).getUrls()})) - .then(onLoad) - }) -} - export const inboxRelaySelections = deriveEventsMapped(repository, { filters: [{kinds: [INBOX_RELAYS]}], itemToEvent: item => item.event, @@ -96,6 +97,5 @@ export const { name: "inboxRelaySelections", store: inboxRelaySelections, getKey: inboxRelaySelections => inboxRelaySelections.event.pubkey, - load: (pubkey: string, relays: string[]) => - loadWithAsapMetaRelayUrls(pubkey, relays, [{kinds: [INBOX_RELAYS], authors: [pubkey]}]), + load: makeOutboxLoader([INBOX_RELAYS]), })