Batch load requests

This commit is contained in:
Jon Staab
2025-03-31 15:52:43 -07:00
parent d0eca0d1b8
commit db588495e3
3 changed files with 55 additions and 19 deletions
+2 -2
View File
@@ -14,7 +14,7 @@ import {
isUnwrappedEvent,
isSignedEvent,
} from "@welshman/util"
import {MultiPublish, PublishStatus, PublishEvent} from "@welshman/net"
import {MultiPublish, AdapterContext, PublishStatus, PublishEvent} from "@welshman/net"
import {repository, tracker} from "./core.js"
import {pubkey, getSession, getSigner} from "./session.js"
@@ -26,7 +26,7 @@ export type ThunkRequest = {
event: ThunkEvent
relays: string[]
delay?: number
context?: AdapterContext,
context?: AdapterContext
}
export type ThunkStatus = {
+52 -16
View File
@@ -1,7 +1,13 @@
import {EventEmitter} from "events"
import {verifyEvent as nostrToolsVerifyEvent} from "nostr-tools/pure"
import {on, call, randomId, yieldThread} from "@welshman/lib"
import {Filter, matchFilter, TrustedEvent, getFilterResultCardinality} from "@welshman/util"
import {on, call, randomId, yieldThread, pushToMapKey, batcher} from "@welshman/lib"
import {
Filter,
unionFilters,
matchFilter,
TrustedEvent,
getFilterResultCardinality,
} from "@welshman/util"
import {RelayMessage, ClientMessageType, isRelayEvent, isRelayEose} from "./message.js"
import {getAdapter, AdapterContext, AbstractAdapter, AdapterEvent} from "./adapter.js"
import {SocketEvent, SocketStatus} from "./socket.js"
@@ -208,23 +214,53 @@ export class MultiRequest extends (EventEmitter as new () => TypedEmitter<MultiR
/**
* A convenience function which returns a promise of events from a request.
* It may return early if filter cardinality is known.
* It may return early if filter cardinality is known, and it delays requests by
* 200 in order to implement batching
* @param options - MultiRequestOptions
* @returns - a promise containing an array of TrustedEvents
*/
export const load = (options: MultiRequestOptions) =>
new Promise(resolve => {
const cardinality = getFilterResultCardinality(options.filter)
const req = new MultiRequest({timeout: 5000, ...options, autoClose: true})
const events: TrustedEvent[] = []
export const load = batcher(200, async (requests: MultiRequestOptions[]) => {
const filtersByRelay = new Map<string, Filter[]>()
req.on(RequestEvent.Event, (event: TrustedEvent) => {
events.push(event)
for (const {filter, relays} of requests) {
for (const relay of relays) {
pushToMapKey(filtersByRelay, relay, filter)
}
}
if (events.length === cardinality) {
resolve(events)
}
})
const tracker = new Tracker()
const events: TrustedEvent[] = []
req.on(RequestEvent.Close, () => resolve(events))
})
await Promise.all(
Array.from(filtersByRelay).map(async ([relay, filters]) => {
await Promise.all(
unionFilters(filters).map(filter => {
new Promise<void>(resolve => {
const cardinality = getFilterResultCardinality(filter)
const req = new MultiRequest({
filter,
tracker,
relays: [relay],
timeout: 5000,
autoClose: true,
})
let count = 0
req.on(RequestEvent.Event, (event: TrustedEvent) => {
events.push(event)
if (++count === cardinality) {
resolve()
}
})
req.on(RequestEvent.Close, () => resolve())
})
}),
)
}),
)
return requests.map(r => events.filter(event => matchFilter(r.filter, event)))
})
+1 -1
View File
@@ -245,7 +245,7 @@ export const getFilterResultCardinality = (filter: Filter) => {
return filter.ids.length
}
return null
return undefined
}
export const trimFilter = (filter: Filter): Filter =>