Split router out into its own library
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import {Repository} from "@welshman/relay"
|
||||
import {verifyEvent, TrustedEvent, SignedEvent} from "@welshman/util"
|
||||
import {verifyEvent, TrustedEvent} from "@welshman/util"
|
||||
import {AbstractAdapter} from "./adapter.js"
|
||||
import {Pool} from "./pool.js"
|
||||
|
||||
@@ -12,8 +12,8 @@ export type NetContext = {
|
||||
}
|
||||
|
||||
export const netContext: NetContext = {
|
||||
pool: Pool.getSingleton(),
|
||||
repository: Repository.getSingleton(),
|
||||
pool: Pool.get(),
|
||||
repository: Repository.get(),
|
||||
isEventValid: (event, url) => verifyEvent(event),
|
||||
isEventDeleted: (event, url) => netContext.repository.isDeleted(event),
|
||||
}
|
||||
|
||||
+12
-11
@@ -200,17 +200,18 @@ export const pull = async ({context, ...options}: PullOptions) => {
|
||||
await Promise.all(
|
||||
Array.from(idsByRelay.entries()).map(([relay, allIds]) => {
|
||||
return Promise.all(
|
||||
chunk(500, allIds).map(ids =>
|
||||
new Promise<void>(resolve =>
|
||||
requestOne({
|
||||
relay,
|
||||
context,
|
||||
filters: [{ids}],
|
||||
autoClose: true,
|
||||
onClose: resolve,
|
||||
onEvent: event => result.push(event as SignedEvent),
|
||||
})
|
||||
)
|
||||
chunk(500, allIds).map(
|
||||
ids =>
|
||||
new Promise<void>(resolve =>
|
||||
requestOne({
|
||||
relay,
|
||||
context,
|
||||
filters: [{ids}],
|
||||
autoClose: true,
|
||||
onClose: resolve,
|
||||
onEvent: event => result.push(event as SignedEvent),
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
}),
|
||||
|
||||
@@ -25,7 +25,7 @@ export class Pool {
|
||||
_data = new Map<string, Socket>()
|
||||
_subs: PoolSubscription[] = []
|
||||
|
||||
static getSingleton() {
|
||||
static get() {
|
||||
if (!poolSingleton) {
|
||||
poolSingleton = new Pool()
|
||||
}
|
||||
|
||||
+18
-23
@@ -1,8 +1,6 @@
|
||||
import {EventEmitter} from "events"
|
||||
import {on, fromPairs, sleep, yieldThread} from "@welshman/lib"
|
||||
import {SignedEvent} from "@welshman/util"
|
||||
import {RelayMessage, ClientMessageType, isRelayOk} from "./message.js"
|
||||
import {AbstractAdapter, AdapterEvent, AdapterContext, getAdapter} from "./adapter.js"
|
||||
import {AdapterEvent, AdapterContext, getAdapter} from "./adapter.js"
|
||||
|
||||
export enum PublishStatus {
|
||||
Sending = "publish:status:sending",
|
||||
@@ -46,28 +44,25 @@ export const publishOne = (options: PublishOneOptions) =>
|
||||
resolve(status)
|
||||
}
|
||||
|
||||
adapter.on(
|
||||
AdapterEvent.Receive,
|
||||
(message: RelayMessage, url: string) => {
|
||||
if (isRelayOk(message)) {
|
||||
const [_, id, ok, detail] = message
|
||||
adapter.on(AdapterEvent.Receive, (message: RelayMessage, url: string) => {
|
||||
if (isRelayOk(message)) {
|
||||
const [_, id, ok, detail] = message
|
||||
|
||||
if (id !== options.event.id) return
|
||||
if (id !== options.event.id) return
|
||||
|
||||
if (ok) {
|
||||
status = PublishStatus.Success
|
||||
options.onSuccess?.(detail)
|
||||
} else {
|
||||
status = PublishStatus.Failure
|
||||
options.onFailure?.(detail)
|
||||
}
|
||||
|
||||
cleanup()
|
||||
if (ok) {
|
||||
status = PublishStatus.Success
|
||||
options.onSuccess?.(detail)
|
||||
} else {
|
||||
status = PublishStatus.Failure
|
||||
options.onFailure?.(detail)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
options.signal?.addEventListener('abort', () => {
|
||||
cleanup()
|
||||
}
|
||||
})
|
||||
|
||||
options.signal?.addEventListener("abort", () => {
|
||||
if (status === PublishStatus.Pending) {
|
||||
status = PublishStatus.Aborted
|
||||
options.onAborted?.()
|
||||
@@ -149,8 +144,8 @@ export const publish = async (options: PublishOptions) => {
|
||||
options.onComplete?.()
|
||||
}
|
||||
},
|
||||
})
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
return status
|
||||
|
||||
+52
-45
@@ -1,5 +1,16 @@
|
||||
import {EventEmitter} from "events"
|
||||
import {on, uniq, lt, flatten, addToMapKey, defer, Deferred, call, randomId, yieldThread, pushToMapKey, batcher} from "@welshman/lib"
|
||||
import {
|
||||
on,
|
||||
uniq,
|
||||
lt,
|
||||
flatten,
|
||||
addToMapKey,
|
||||
defer,
|
||||
Deferred,
|
||||
call,
|
||||
randomId,
|
||||
pushToMapKey,
|
||||
batcher,
|
||||
} from "@welshman/lib"
|
||||
import {
|
||||
Filter,
|
||||
getAddress,
|
||||
@@ -9,9 +20,8 @@ import {
|
||||
getFilterResultCardinality,
|
||||
} from "@welshman/util"
|
||||
import {RelayMessage, ClientMessageType, isRelayEvent, isRelayEose} from "./message.js"
|
||||
import {getAdapter, AdapterContext, AbstractAdapter, AdapterEvent} from "./adapter.js"
|
||||
import {getAdapter, AdapterContext, AdapterEvent} from "./adapter.js"
|
||||
import {SocketEvent, SocketStatus} from "./socket.js"
|
||||
import {Unsubscriber} from "./util.js"
|
||||
import {netContext} from "./context.js"
|
||||
import {Tracker} from "./tracker.js"
|
||||
|
||||
@@ -160,7 +170,6 @@ export const request = async (options: RequestOptions) => {
|
||||
const ctrl = new AbortController()
|
||||
const signal = options.signal ? AbortSignal.any([options.signal, ctrl.signal]) : ctrl.signal
|
||||
const threshold = options.threshold || 1
|
||||
const promises: Promise<TrustedEvent[]>[] = []
|
||||
|
||||
if (relays.size !== options.relays.length) {
|
||||
console.warn("Non-unique relays passed to request")
|
||||
@@ -181,14 +190,13 @@ export const request = async (options: RequestOptions) => {
|
||||
options.onClose?.()
|
||||
ctrl.abort()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
},
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export type LoaderOptions = {
|
||||
delay: number
|
||||
timeout?: number
|
||||
@@ -251,7 +259,7 @@ export const makeLoader = (options: LoaderOptions) =>
|
||||
resultsByRequest.set(request, defer())
|
||||
|
||||
// Propagate abort when all requests have been closed for a given relay
|
||||
request.signal?.addEventListener('abort', () => close(relay, request))
|
||||
request.signal?.addEventListener("abort", () => close(relay, request))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,47 +276,46 @@ export const makeLoader = (options: LoaderOptions) =>
|
||||
signalsByRelay.set(relay, AbortSignal.any(signals))
|
||||
}
|
||||
|
||||
Array.from(requestsByRelay).forEach(
|
||||
async ([relay, requests]) => {
|
||||
// Union all filters for a given request and send them together
|
||||
const filters = unionFilters(requests.flatMap(r => r.filters))
|
||||
Array.from(requestsByRelay).forEach(async ([relay, requests]) => {
|
||||
// Union all filters for a given request and send them together
|
||||
const filters = unionFilters(requests.flatMap(r => r.filters))
|
||||
|
||||
// Propagate events to caller, but only for requests that have not been aborted
|
||||
const getOpenRequests = () =>
|
||||
requests.filter(request => !closedRequestsByRelay.get(relay)?.has(request))
|
||||
// Propagate events to caller, but only for requests that have not been aborted
|
||||
const getOpenRequests = () =>
|
||||
requests.filter(request => !closedRequestsByRelay.get(relay)?.has(request))
|
||||
|
||||
requestOne({
|
||||
relay,
|
||||
filters,
|
||||
tracker,
|
||||
autoClose: true,
|
||||
signal: signalsByRelay.get(relay),
|
||||
context: options.context,
|
||||
isEventValid: options.isEventValid,
|
||||
isEventDeleted: options.isEventDeleted,
|
||||
onEvent: (event: TrustedEvent, url: string) => {
|
||||
for (const request of getOpenRequests()) {
|
||||
if (matchFilters(request.filters, event)) {
|
||||
pushToMapKey(eventsByRequest, request, event)
|
||||
request.onEvent?.(event, url)
|
||||
requestOne({
|
||||
relay,
|
||||
filters,
|
||||
tracker,
|
||||
autoClose: true,
|
||||
signal: signalsByRelay.get(relay),
|
||||
context: options.context,
|
||||
isEventValid: options.isEventValid,
|
||||
isEventDeleted: options.isEventDeleted,
|
||||
onEvent: (event: TrustedEvent, url: string) => {
|
||||
for (const request of getOpenRequests()) {
|
||||
if (matchFilters(request.filters, event)) {
|
||||
pushToMapKey(eventsByRequest, request, event)
|
||||
request.onEvent?.(event, url)
|
||||
|
||||
// Calculate cardinality for unioned filters so that we can return early
|
||||
if (request.filters.length === 1) {
|
||||
const cardinality = getFilterResultCardinality(request.filters[0])
|
||||
// Calculate cardinality for unioned filters so that we can return early
|
||||
if (request.filters.length === 1) {
|
||||
const cardinality = getFilterResultCardinality(request.filters[0])
|
||||
|
||||
if (eventsByRequest.get(request)?.length === cardinality) {
|
||||
close(relay, request)
|
||||
}
|
||||
if (eventsByRequest.get(request)?.length === cardinality) {
|
||||
close(relay, request)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onDisconnect: (url: string) => getOpenRequests().forEach(request => request.onDisconnect?.(url)),
|
||||
onEose: (url: string) => getOpenRequests().forEach(request => request.onEose?.(url)),
|
||||
onClose: () => requests.forEach(request => close(relay, request)),
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
onDisconnect: (url: string) =>
|
||||
getOpenRequests().forEach(request => request.onDisconnect?.(url)),
|
||||
onEose: (url: string) => getOpenRequests().forEach(request => request.onEose?.(url)),
|
||||
onClose: () => requests.forEach(request => close(relay, request)),
|
||||
})
|
||||
})
|
||||
|
||||
return allRequests.map(r => resultsByRequest.get(r)!)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user