@relaybus/mongodb 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +251 -88
- package/dist/index.cjs +1957 -510
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +159 -20
- package/dist/index.d.ts +159 -20
- package/dist/index.js +1958 -511
- package/dist/index.js.map +1 -1
- package/package.json +22 -9
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/claim-scan.ts","../src/documents.ts","../src/mongo-errors.ts","../src/naming.ts","../src/mongo-event-store.ts"],"names":["EventValidationError","ConfigurationError","createUuidV7"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { DeliveryDocument } from './documents.js';\n\n/** What one claim call has learned about the deliveries of a single handler and key. */\ninterface KeyKnowledge {\n /** Lowest sequence known to be unfinished. Every later delivery of the key must wait. */\n openSequence: number | undefined;\n /** Whether some delivery of the key holds a live lease, so none may start. */\n leaseHeld: boolean;\n /** Pending deliveries that waited behind `openSequence`, candidates for parking. */\n waiting: string[];\n}\n\nexport type KeyVerdict = 'open-predecessor' | 'live-lease';\n\n/**\n * Bookkeeping of one claim call. A claim scans due deliveries in due order and\n * meets many deliveries of the same key; whatever it learns about a key from\n * the database once (an unfinished predecessor, a live lease, its own claim)\n * answers every later delivery of that key without another query.\n */\nexport class ClaimScan {\n readonly #keys = new Map<string, KeyKnowledge>();\n\n /** Why the delivery must wait according to what this scan already knows, if it does. */\n verdict(orderingId: string, sequence: number): KeyVerdict | undefined {\n const known = this.#keys.get(orderingId);\n if (known?.openSequence !== undefined && sequence > known.openSequence) {\n return 'open-predecessor';\n }\n return known?.leaseHeld === true ? 'live-lease' : undefined;\n }\n\n /** Records an unfinished delivery of the key with this sequence. */\n noteOpen(orderingId: string, sequence: number): void {\n const known = this.#know(orderingId);\n known.openSequence = Math.min(known.openSequence ?? sequence, sequence);\n }\n\n /** Records that this scan leased the delivery, which is now unfinished and holds a live lease. */\n noteClaimed(orderingId: string, sequence: number): void {\n this.noteOpen(orderingId, sequence);\n this.#know(orderingId).leaseHeld = true;\n }\n\n /** Records that a live lease of the key blocks every delivery of it. */\n noteLeaseHeld(orderingId: string): void {\n this.#know(orderingId).leaseHeld = true;\n }\n\n /** Remembers a delivery that waited behind an unfinished predecessor. */\n noteWaiting(orderingId: string, delivery: DeliveryDocument): void {\n if (delivery.status === 'pending') {\n this.#know(orderingId).waiting.push(delivery._id);\n }\n }\n\n /**\n * Ids of the waiting deliveries of every key that accumulated at least\n * `minimum` of them. Shorter queues stay in the claim index: moving them out\n * and back would cost more than skipping them.\n */\n waitingBacklogs(minimum: number): string[] {\n return [...this.#keys.values()]\n .filter((known) => known.waiting.length >= minimum)\n .flatMap((known) => known.waiting);\n }\n\n #know(orderingId: string): KeyKnowledge {\n let known = this.#keys.get(orderingId);\n if (known === undefined) {\n known = { openSequence: undefined, leaseHeld: false, waiting: [] };\n this.#keys.set(orderingId, known);\n }\n return known;\n }\n}\n\n/** Identity of the ordering lane of a handler and key. */\nexport function orderingIdentity(handler: string, key: string): string {\n return `${handler}\\u0000${key}`;\n}\n","import {\n EventValidationError,\n type DeliveryRecord,\n type DeliveryStatus,\n type ErrorInfo,\n type EventEnvelope,\n type NewDelivery,\n} from '@relaybus/core';\n\n/** Where a delivery sits relative to the claim index. See {@link DeliveryDocument.lane}. */\nexport type DeliveryLane = 'ready' | 'parked';\n\n/** Shape of a document in the events collection. `_id` is the event id. */\nexport interface EventDocument {\n readonly _id: string;\n readonly type: string;\n readonly source: string;\n readonly key: string | null;\n /** Position among the events of the same key, in commit order. Null for unkeyed events. */\n readonly sequence: number | null;\n /** JSON-normalized payload. Absent when the published payload was `undefined`. */\n readonly payload?: unknown;\n readonly headers: Readonly<Record<string, string>>;\n readonly correlationId: string | null;\n readonly causationId: string | null;\n readonly occurredAt: Date;\n /** Incremented when deliveries are added to an already stored event, so a concurrent purge conflicts with it. */\n readonly revision: number;\n}\n\n/**\n * Shape of a document in the deliveries collection.\n *\n * `dueAt` exists exactly while the delivery is `pending` (its `availableAt`) or\n * `processing` (its `leaseExpiresAt`). The ordering index is partial on it, so\n * it only ever contains unfinished work.\n *\n * `lane` exists on the same deliveries. A `ready` delivery is in the claim\n * index. A `parked` delivery is a pending, keyed delivery that waited behind an\n * unfinished earlier delivery of its handler and key; the claim index leaves it\n * out so a long queue behind one slow delivery costs nothing per claim. Claims\n * move the lowest parked delivery of a key back to `ready` once nothing\n * unfinished precedes it.\n */\nexport interface DeliveryDocument {\n readonly _id: string;\n readonly eventId: string;\n readonly eventType: string;\n readonly handler: string;\n /** Ordering key. Absent for unkeyed events. */\n readonly key?: string;\n /** Sequence of the event within its key. Absent for unkeyed events. */\n readonly sequence?: number;\n readonly status: DeliveryStatus;\n readonly lane?: DeliveryLane;\n readonly attempts: number;\n readonly availableAt: Date;\n readonly dueAt?: Date;\n readonly leaseOwner?: string;\n readonly leaseToken?: string;\n readonly leaseExpiresAt?: Date;\n readonly lastError?: ErrorInfo;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n readonly completedAt?: Date;\n}\n\n/** Shape of a document in the key sequences collection. `_id` is the ordering key. */\nexport interface KeySequenceDocument {\n readonly _id: string;\n readonly value: number;\n}\n\n/**\n * Builds the stored form of an event. Payload and headers go through JSON so\n * that values JSON cannot represent (Dates, `undefined`, `NaN`) end up exactly\n * as in every other store.\n *\n * @throws EventValidationError when payload or headers contain a lone UTF-16\n * surrogate. BSON strings are UTF-8, so MongoDB would silently store U+FFFD\n * instead and the consumer would read different data than was published.\n */\nexport function toEventDocument(event: EventEnvelope, sequence: number | null): EventDocument {\n const payloadJson = serializeWellFormed(event.payload, 'payload');\n const headersJson = serializeWellFormed(event.headers, 'headers')!;\n return {\n _id: event.id,\n type: event.type,\n source: event.source,\n key: event.key,\n sequence,\n ...(payloadJson === undefined ? {} : { payload: JSON.parse(payloadJson) as unknown }),\n headers: JSON.parse(headersJson) as Record<string, string>,\n correlationId: event.correlationId,\n causationId: event.causationId,\n occurredAt: event.occurredAt,\n revision: 0,\n };\n}\n\n/**\n * JSON.stringify writes a lone surrogate as a `\\udXXX` escape and a valid pair as\n * the character itself, so an escape in that range is exactly a lone surrogate.\n * The lookbehind and the pair group skip escaped backslashes (`\\\\ud800` is text).\n */\nconst LONE_SURROGATE_ESCAPE = /(?<!\\\\)(?:\\\\\\\\)*\\\\ud[89a-f][0-9a-f]{2}/i;\n\nfunction serializeWellFormed(value: unknown, field: string): string | undefined {\n const json = JSON.stringify(value);\n if (json !== undefined && LONE_SURROGATE_ESCAPE.test(json)) {\n throw new EventValidationError(`The event ${field} contains a lone UTF-16 surrogate`, [\n {\n message:\n 'A lone surrogate cannot be stored as UTF-8 and would be replaced by U+FFFD. Remove it or encode the text first (for example with String.prototype.toWellFormed)',\n path: [field],\n },\n ]);\n }\n return json;\n}\n\nexport function toEnvelope(document: EventDocument): EventEnvelope {\n return {\n id: document._id,\n type: document.type,\n source: document.source,\n key: document.key,\n payload: document.payload,\n headers: document.headers,\n correlationId: document.correlationId,\n causationId: document.causationId,\n occurredAt: document.occurredAt,\n };\n}\n\nexport function toDeliveryDocument(\n delivery: NewDelivery,\n event: Pick<EventEnvelope, 'id' | 'type'>,\n ordering: { readonly key: string | null; readonly sequence: number | null },\n now: Date,\n): DeliveryDocument {\n return {\n _id: delivery.id,\n eventId: event.id,\n eventType: event.type,\n handler: delivery.handler,\n ...(ordering.key === null || ordering.sequence === null\n ? {}\n : { key: ordering.key, sequence: ordering.sequence }),\n status: 'pending',\n lane: 'ready',\n attempts: 0,\n availableAt: delivery.availableAt,\n dueAt: delivery.availableAt,\n createdAt: now,\n updatedAt: now,\n };\n}\n\nexport function toDeliveryRecord(document: DeliveryDocument, event: EventEnvelope): DeliveryRecord {\n return {\n id: document._id,\n handler: document.handler,\n status: document.status,\n attempts: document.attempts,\n availableAt: document.availableAt,\n leaseOwner: document.leaseOwner ?? null,\n leaseExpiresAt: document.leaseExpiresAt ?? null,\n lastError: document.lastError === undefined ? null : toErrorInfo(document.lastError),\n createdAt: document.createdAt,\n updatedAt: document.updatedAt,\n completedAt: document.completedAt ?? null,\n event,\n };\n}\n\n/** Copies an error without `undefined` members, which BSON would store as null. */\nexport function toErrorInfo(error: ErrorInfo): ErrorInfo {\n return error.stack === undefined\n ? { name: error.name, message: error.message }\n : { name: error.name, message: error.message, stack: error.stack };\n}\n","import { ConfigurationError } from '@relaybus/core';\n\nconst ILLEGAL_OPERATION = 20;\n\n/** True for the server error raised when a transaction runs on a standalone mongod. */\nexport function isTransactionsUnsupportedError(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === ILLEGAL_OPERATION &&\n 'message' in error &&\n typeof error.message === 'string' &&\n error.message.includes('replica set member or mongos')\n );\n}\n\nexport function createTransactionsUnsupportedError(cause: unknown): ConfigurationError {\n return new ConfigurationError(\n 'MongoEventStore needs multi-document transactions, which MongoDB only offers on a replica set or a sharded cluster. Run a single-node replica set for development (mongod --replSet rs0, then rs.initiate())',\n { cause },\n );\n}\n","import { ConfigurationError } from '@relaybus/core';\n\nconst COLLECTION_PREFIX_PATTERN = /^[A-Za-z_][A-Za-z0-9_]{0,39}$/;\nconst DATABASE_NAME_PATTERN = /^[A-Za-z0-9_-]{1,63}$/;\n\n/** Rejects prefixes that are not safe, portable collection name starts. */\nexport function assertCollectionPrefix(prefix: string): void {\n if (!COLLECTION_PREFIX_PATTERN.test(prefix)) {\n throw new ConfigurationError(\n `collectionPrefix '${prefix}' must be 1-40 characters of letters, digits or '_', starting with a letter or '_'`,\n );\n }\n}\n\n/** Rejects database names MongoDB would refuse or that need escaping. */\nexport function assertDatabaseName(name: string): void {\n if (!DATABASE_NAME_PATTERN.test(name)) {\n throw new ConfigurationError(\n `database '${name}' must be 1-63 characters of letters, digits, '_' or '-'`,\n );\n }\n}\n","import {\n ConfigurationError,\n createUuidV7,\n type AppendEntry,\n type AppendResult,\n type ClaimRequest,\n type ClaimedDelivery,\n type DeliveryQuery,\n type DeliveryRecord,\n type DeliveryStatus,\n type ErrorInfo,\n type EventEnvelope,\n type EventStore,\n type EventStoreStatistics,\n type IdentifierGenerator,\n type LeaseReference,\n type PurgeRequest,\n type PurgeResult,\n} from '@relaybus/core';\nimport type {\n ClientSession,\n Collection,\n Db,\n Filter,\n MongoClient,\n TransactionOptions,\n UpdateFilter,\n} from 'mongodb';\nimport { ClaimScan, orderingIdentity } from './claim-scan.js';\nimport {\n toDeliveryDocument,\n toDeliveryRecord,\n toEnvelope,\n toErrorInfo,\n toEventDocument,\n type DeliveryDocument,\n type EventDocument,\n type KeySequenceDocument,\n} from './documents.js';\nimport {\n createTransactionsUnsupportedError,\n isTransactionsUnsupportedError,\n} from './mongo-errors.js';\nimport { assertCollectionPrefix, assertDatabaseName } from './naming.js';\n\nexport interface MongoEventStoreOptions {\n /** Connected client. The store never closes it. */\n readonly client: MongoClient;\n /** Database holding the relaybus collections. Default: the client's default database. */\n readonly database?: string;\n /** Prefix of the three collection names. Default `relaybus_`. */\n readonly collectionPrefix?: string;\n /**\n * Options of the transactions the store opens. Default: snapshot read\n * concern, majority write concern, primary reads.\n */\n readonly transactionOptions?: TransactionOptions;\n /** Rows deleted per purge step. Default 500. */\n readonly purgeBatchSize?: number;\n /** Produces lease tokens. Default UUID v7. */\n readonly generateIdentifier?: IdentifierGenerator;\n}\n\nconst DEFAULT_TRANSACTION_OPTIONS: TransactionOptions = {\n readConcern: { level: 'snapshot' },\n writeConcern: { w: 'majority' },\n readPreference: 'primary',\n};\nconst NAMESPACE_EXISTS = 48;\nconst DEFAULT_PURGE_BATCH_SIZE = 500;\nconst DEFAULT_LIST_LIMIT = 100;\nconst MINIMUM_CANDIDATE_BATCH_SIZE = 32;\n/** Deliveries that waited behind one unfinished predecessor before they are parked. */\nconst PARK_BACKLOG_THRESHOLD = 32;\nconst PARK_UPDATE_CHUNK_SIZE = 1_000;\n\n/** Fields that exist only while a delivery is leased. */\nconst LEASE_FIELDS = { leaseOwner: '', leaseToken: '', leaseExpiresAt: '' } as const;\n/** Fields that exist only while a delivery is unfinished. */\nconst FINISHED_FIELDS = { dueAt: '', lane: '' } as const;\n\n/**\n * Event store on MongoDB 6+ multi-document transactions (replica set or sharded\n * cluster). The transaction handle is the driver's `ClientSession`, so the same\n * session can carry your own writes (native driver or Mongoose).\n *\n * Guarantees:\n * - `append` is atomic with the caller's writes and idempotent on event id and on\n * (event id, handler). Duplicates are detected by reading, never by catching a\n * duplicate-key error, which would abort the surrounding transaction.\n * - Per-key sequences are allocated from a counter document inside the append\n * transaction. Two transactions appending the same key cannot both hold the\n * counter, so the loser conflicts, restarts after the winner committed, and\n * its sequence is higher: sequence order is commit order.\n * - `claim` selects candidates, then takes each with a conditional update that\n * re-checks the exact state it selected, so exactly one claimer wins. A keyed\n * delivery waits while an earlier delivery of its handler and key is\n * unfinished, or while any other delivery of them runs under a live lease;\n * the second rule is re-checked after the update, so a dead letter requeued\n * during a claim cannot run alongside its successor.\n * - Every lease operation is fenced by delivery id, status and lease token.\n *\n * `transaction` may run `work` more than once (see {@link MongoEventStore.transaction}).\n */\nexport class MongoEventStore implements EventStore<ClientSession> {\n readonly #client: MongoClient;\n readonly #database: Db;\n readonly #events: Collection<EventDocument>;\n readonly #deliveries: Collection<DeliveryDocument>;\n readonly #keySequences: Collection<KeySequenceDocument>;\n readonly #transactionOptions: TransactionOptions;\n readonly #purgeBatchSize: number;\n readonly #generateIdentifier: IdentifierGenerator;\n\n constructor(options: MongoEventStoreOptions) {\n const prefix = options.collectionPrefix ?? 'relaybus_';\n assertCollectionPrefix(prefix);\n if (options.database !== undefined) {\n assertDatabaseName(options.database);\n }\n const purgeBatchSize = options.purgeBatchSize ?? DEFAULT_PURGE_BATCH_SIZE;\n if (!Number.isInteger(purgeBatchSize) || purgeBatchSize < 1) {\n throw new ConfigurationError(\n `purgeBatchSize must be a positive integer, received ${String(purgeBatchSize)}`,\n );\n }\n this.#client = options.client;\n const database = options.client.db(options.database);\n this.#database = database;\n // Majority writes make a lease durable; primary reads keep the ordering check fresh.\n const collectionOptions = {\n readPreference: 'primary',\n writeConcern: { w: 'majority' },\n } as const;\n this.#events = database.collection(`${prefix}events`, collectionOptions);\n this.#deliveries = database.collection(`${prefix}deliveries`, collectionOptions);\n this.#keySequences = database.collection(`${prefix}key_sequences`, collectionOptions);\n this.#transactionOptions = options.transactionOptions ?? DEFAULT_TRANSACTION_OPTIONS;\n this.#purgeBatchSize = purgeBatchSize;\n this.#generateIdentifier = options.generateIdentifier ?? (() => createUuidV7());\n }\n\n /**\n * Verifies the deployment supports transactions and creates the indexes.\n * Safe to run repeatedly and from several processes.\n *\n * @throws ConfigurationError when the server is a standalone mongod.\n */\n async setup(): Promise<void> {\n const hello = await this.#client.db('admin').command({ hello: 1 });\n const supportsTransactions =\n typeof hello['setName'] === 'string' || hello['msg'] === 'isdbgrid';\n if (!supportsTransactions) {\n throw createTransactionsUnsupportedError(undefined);\n }\n // Created up front: collections created implicitly inside concurrent transactions conflict.\n for (const collection of [this.#events, this.#deliveries, this.#keySequences]) {\n await this.#createCollectionIfMissing(collection.collectionName);\n }\n await this.#deliveries.createIndexes([\n // Idempotent appends and lookups by event.\n { key: { eventId: 1, handler: 1 }, name: 'event_handler', unique: true },\n // Claim: due work of a handler in due order. Holds ready deliveries only.\n {\n key: { handler: 1, dueAt: 1, _id: 1 },\n name: 'claim',\n partialFilterExpression: { lane: 'ready' },\n },\n // Ordering: unfinished predecessors of a keyed delivery, parked or not.\n {\n key: { handler: 1, key: 1, sequence: 1 },\n name: 'ordering',\n partialFilterExpression: { dueAt: { $exists: true }, sequence: { $exists: true } },\n },\n // Parked deliveries: the lowest parked delivery of each key, to move it back once it is next.\n {\n key: { handler: 1, key: 1, sequence: 1 },\n name: 'parked',\n partialFilterExpression: { lane: 'parked' },\n },\n // Live leases: a keyed delivery may not start while another of its key is running.\n {\n key: { handler: 1, key: 1, dueAt: 1 },\n name: 'running',\n partialFilterExpression: { status: 'processing', key: { $exists: true } },\n },\n // Statistics: oldest due delivery across handlers.\n { key: { dueAt: 1 }, name: 'due', partialFilterExpression: { dueAt: { $exists: true } } },\n // Purge of completed deliveries.\n {\n key: { completedAt: 1 },\n name: 'completed',\n partialFilterExpression: { completedAt: { $exists: true } },\n },\n // Listing and status counts.\n { key: { status: 1, createdAt: 1 }, name: 'status_created' },\n // Purge of dead deliveries.\n { key: { status: 1, updatedAt: 1 }, name: 'status_updated' },\n { key: { handler: 1, createdAt: 1 }, name: 'handler_created' },\n { key: { eventType: 1, createdAt: 1 }, name: 'type_created' },\n ]);\n }\n\n async #createCollectionIfMissing(name: string): Promise<void> {\n try {\n await this.#database.createCollection(name);\n } catch (error) {\n if (!(\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === NAMESPACE_EXISTS\n )) {\n throw error;\n }\n }\n }\n\n /**\n * Runs `work` in a transaction on a new session and commits when it resolves.\n *\n * `work` can run more than once. The driver restarts the whole callback after\n * a transient failure such as a write conflict, and re-sends only the commit\n * after an unknown commit result. A restart is safe for everything written\n * through the session, because the aborted attempt left nothing behind. It is\n * not safe for side effects outside the session (HTTP calls, other databases),\n * so keep those out of `work`; relaybus handlers are already at-least-once.\n *\n * @throws ConfigurationError when the deployment does not support transactions.\n */\n async transaction<T>(work: (transaction: ClientSession) => Promise<T>): Promise<T> {\n try {\n return await this.#client.withSession(async (session) => {\n let result!: T;\n await session.withTransaction(async () => {\n result = await work(session);\n }, this.#transactionOptions);\n return result;\n });\n } catch (error) {\n if (isTransactionsUnsupportedError(error)) {\n throw createTransactionsUnsupportedError(error);\n }\n throw error;\n }\n }\n\n async append(\n session: ClientSession,\n entries: readonly AppendEntry[],\n now: Date,\n ): Promise<AppendResult> {\n assertInTransaction(session, 'append');\n const eventIds = [...new Set(entries.map((entry) => entry.event.id))];\n const storedEvents = new Map(\n (\n await this.#events\n .find({ _id: { $in: eventIds } }, { session, projection: { key: 1, sequence: 1 } })\n .toArray()\n ).map((stored) => [stored._id, stored]),\n );\n const storedDeliveryKeys = new Set(\n (\n await this.#deliveries\n .find({ eventId: { $in: eventIds } }, { session, projection: { eventId: 1, handler: 1 } })\n .toArray()\n ).map((stored) => deliveryPairKey(stored.eventId, stored.handler)),\n );\n\n const appendedEventIds: string[] = [];\n const duplicateEventIds: string[] = [];\n const newEvents: EventDocument[] = [];\n const newDeliveries: DeliveryDocument[] = [];\n const touchedEventIds = new Set<string>();\n const orderingByEventId = new Map<\n string,\n { readonly key: string | null; readonly sequence: number | null }\n >();\n for (const [eventId, stored] of storedEvents) {\n orderingByEventId.set(eventId, { key: stored.key, sequence: stored.sequence });\n }\n\n for (const { event, deliveries } of entries) {\n let ordering = orderingByEventId.get(event.id);\n if (ordering === undefined) {\n const sequence = event.key === null ? null : await this.#nextSequence(event.key, session);\n ordering = { key: event.key, sequence };\n orderingByEventId.set(event.id, ordering);\n newEvents.push(toEventDocument(event, sequence));\n appendedEventIds.push(event.id);\n } else {\n duplicateEventIds.push(event.id);\n }\n for (const delivery of deliveries) {\n const pairKey = deliveryPairKey(event.id, delivery.handler);\n if (storedDeliveryKeys.has(pairKey)) {\n continue;\n }\n storedDeliveryKeys.add(pairKey);\n newDeliveries.push(toDeliveryDocument(delivery, event, ordering, now));\n if (storedEvents.has(event.id)) {\n touchedEventIds.add(event.id);\n }\n }\n }\n\n if (newEvents.length > 0) {\n // Upserts, not inserts: a duplicate-key error would abort the whole transaction,\n // whereas a concurrent writer of the same id surfaces as a retryable write conflict.\n await this.#events.bulkWrite(\n newEvents.map((document) => ({\n updateOne: {\n filter: { _id: document._id },\n update: { $setOnInsert: document },\n upsert: true,\n },\n })),\n { session, ordered: true },\n );\n }\n if (touchedEventIds.size > 0) {\n // A real write on the event makes a concurrent purge of it conflict with this transaction.\n await this.#events.updateMany(\n { _id: { $in: [...touchedEventIds] } },\n { $inc: { revision: 1 } },\n { session },\n );\n }\n if (newDeliveries.length > 0) {\n await this.#deliveries.bulkWrite(\n newDeliveries.map((document) => ({\n updateOne: {\n filter: { eventId: document.eventId, handler: document.handler },\n update: { $setOnInsert: document },\n upsert: true,\n },\n })),\n { session, ordered: true },\n );\n }\n return { appendedEventIds, duplicateEventIds, appendedDeliveryCount: newDeliveries.length };\n }\n\n async claim(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n if (request.handlers.length === 0 || request.limit <= 0) {\n return [];\n }\n await this.#unparkNextDeliveries(request.handlers);\n const claimed: DeliveryDocument[] = [];\n const scan = new ClaimScan();\n const candidates = this.#deliveries.find(\n { handler: { $in: [...request.handlers] }, dueAt: { $lte: request.now }, lane: 'ready' },\n {\n sort: { dueAt: 1, _id: 1 },\n batchSize: Math.max(request.limit * 2, MINIMUM_CANDIDATE_BATCH_SIZE),\n },\n );\n try {\n for await (const candidate of candidates) {\n const leased = await this.#claimCandidate(candidate, request, scan);\n if (leased !== undefined) {\n claimed.push(leased);\n if (claimed.length >= request.limit) {\n break;\n }\n }\n }\n } finally {\n await candidates.close();\n }\n await this.#parkDeliveries(scan.waitingBacklogs(PARK_BACKLOG_THRESHOLD));\n return this.#toClaimedDeliveries(claimed, request.leaseExpiresAt);\n }\n\n async extendLease(lease: LeaseReference, leaseExpiresAt: Date, now: Date): Promise<boolean> {\n return this.#updateLeased(lease, undefined, {\n $set: { leaseExpiresAt, dueAt: leaseExpiresAt, updatedAt: now },\n });\n }\n\n async complete(lease: LeaseReference, now: Date, session?: ClientSession): Promise<boolean> {\n if (session !== undefined) {\n assertInTransaction(session, 'complete');\n }\n return this.#updateLeased(lease, session, {\n $set: { status: 'completed', completedAt: now, updatedAt: now },\n $unset: { ...LEASE_FIELDS, ...FINISHED_FIELDS },\n });\n }\n\n async reschedule(\n lease: LeaseReference,\n availableAt: Date,\n error: ErrorInfo,\n now: Date,\n ): Promise<boolean> {\n return this.#updateLeased(lease, undefined, {\n $set: {\n status: 'pending',\n availableAt,\n dueAt: availableAt,\n lastError: toErrorInfo(error),\n updatedAt: now,\n },\n $unset: LEASE_FIELDS,\n });\n }\n\n async release(lease: LeaseReference, now: Date): Promise<boolean> {\n return this.#updateLeased(lease, undefined, {\n $set: { status: 'pending', availableAt: now, dueAt: now, updatedAt: now },\n $inc: { attempts: -1 },\n $unset: LEASE_FIELDS,\n });\n }\n\n async bury(lease: LeaseReference, error: ErrorInfo, now: Date): Promise<boolean> {\n return this.#updateLeased(lease, undefined, {\n $set: { status: 'dead', lastError: toErrorInfo(error), updatedAt: now },\n $unset: { ...LEASE_FIELDS, ...FINISHED_FIELDS },\n });\n }\n\n async listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]> {\n // Strings only: an object here (say, parsed from an admin request) would be a query operator.\n const filter: Filter<DeliveryDocument> = {\n ...(query.status === undefined ? {} : { status: String(query.status) as DeliveryStatus }),\n ...(query.handler === undefined ? {} : { handler: String(query.handler) }),\n ...(query.eventType === undefined ? {} : { eventType: String(query.eventType) }),\n ...(query.eventId === undefined ? {} : { eventId: String(query.eventId) }),\n };\n const documents = await this.#deliveries\n .find(filter, { sort: { createdAt: 1, _id: 1 }, limit: query.limit ?? DEFAULT_LIST_LIMIT })\n .toArray();\n const events = await this.#readEnvelopes(documents.map((document) => document.eventId));\n return documents.map((document) => toDeliveryRecord(document, events.get(document.eventId)!));\n }\n\n async requeue(deliveryIds: readonly string[], now: Date): Promise<number> {\n const result = await this.#deliveries.updateMany(\n { _id: { $in: deliveryIds.map(String) }, status: 'dead' },\n {\n $set: {\n status: 'pending',\n lane: 'ready',\n attempts: 0,\n availableAt: now,\n dueAt: now,\n updatedAt: now,\n },\n },\n );\n return result.modifiedCount;\n }\n\n async purge(request: PurgeRequest): Promise<PurgeResult> {\n const filters: Filter<DeliveryDocument>[] = [];\n if (request.completedBefore !== undefined) {\n filters.push({ status: 'completed', completedAt: { $lt: request.completedBefore } });\n }\n if (request.deadBefore !== undefined) {\n filters.push({ status: 'dead', updatedAt: { $lt: request.deadBefore } });\n }\n let deletedDeliveries = 0;\n let deletedEvents = 0;\n for (const filter of filters) {\n const result = await this.#purgeMatching(filter);\n deletedDeliveries += result.deletedDeliveries;\n deletedEvents += result.deletedEvents;\n }\n return { deletedDeliveries, deletedEvents };\n }\n\n async statistics(now: Date): Promise<EventStoreStatistics> {\n // Four index-only counts: measured at 300k deliveries they take 27 ms in parallel, against\n // 121 ms for one $group, which has to read every document or index entry.\n const statuses: DeliveryStatus[] = ['pending', 'processing', 'completed', 'dead'];\n const [pending, processing, completed, dead] = await Promise.all(\n statuses.map((status) => this.#deliveries.countDocuments({ status })),\n );\n const oldestDue = await this.#deliveries.findOne(\n { dueAt: { $lte: now } },\n { sort: { dueAt: 1 }, projection: { dueAt: 1 } },\n );\n return {\n pending: pending!,\n processing: processing!,\n completed: completed!,\n dead: dead!,\n oldestDueAt: oldestDue?.dueAt ?? null,\n };\n }\n\n /** Atomically increments the counter of `key`; conflicting appends of the key serialize here. */\n async #nextSequence(key: string, session: ClientSession): Promise<number> {\n const counter = await this.#keySequences.findOneAndUpdate(\n { _id: key },\n { $inc: { value: 1 } },\n { upsert: true, returnDocument: 'after', session },\n );\n return counter!.value;\n }\n\n async #claimCandidate(\n candidate: DeliveryDocument,\n request: ClaimRequest,\n scan: ClaimScan,\n ): Promise<DeliveryDocument | undefined> {\n const { key, sequence } = candidate;\n if (key === undefined) {\n return this.#lease(candidate, request);\n }\n const orderingId = orderingIdentity(candidate.handler, key);\n const known = scan.verdict(orderingId, sequence!);\n if (known === 'open-predecessor') {\n scan.noteWaiting(orderingId, candidate);\n return undefined;\n }\n if (known === 'live-lease') {\n return undefined;\n }\n const predecessor = await this.#findUnfinishedPredecessor(candidate.handler, key, sequence!);\n if (predecessor !== undefined) {\n scan.noteOpen(orderingId, predecessor);\n scan.noteWaiting(orderingId, candidate);\n return undefined;\n }\n if (await this.#hasLiveLease(candidate.handler, key, request.now)) {\n scan.noteLeaseHeld(orderingId);\n return undefined;\n }\n const leased = await this.#lease(candidate, request);\n if (leased === undefined) {\n return undefined;\n }\n // A dead letter requeued after the checks above can be claimed by another worker\n // before this lease is visible to it, and neither check would see the other. Only\n // the later delivery gives way, so exactly one of the two keeps running.\n const lateBlocker = await this.#findUnfinishedPredecessor(candidate.handler, key, sequence!);\n if (lateBlocker !== undefined) {\n await this.#restore(candidate, leased);\n scan.noteOpen(orderingId, lateBlocker);\n return undefined;\n }\n scan.noteClaimed(orderingId, sequence!);\n return leased;\n }\n\n /**\n * Takes the delivery with one conditional update that pins the exact state\n * that was selected, so a competing claimer, a finished lease, a reschedule\n * or a parking since then makes it match nothing.\n */\n async #lease(\n candidate: DeliveryDocument,\n request: ClaimRequest,\n ): Promise<DeliveryDocument | undefined> {\n const leased = await this.#deliveries.findOneAndUpdate(\n {\n _id: candidate._id,\n status: candidate.status,\n lane: 'ready',\n attempts: candidate.attempts,\n dueAt: candidate.dueAt!,\n },\n {\n $set: {\n status: 'processing',\n leaseOwner: request.leaseOwner,\n leaseToken: this.#generateIdentifier(),\n leaseExpiresAt: request.leaseExpiresAt,\n dueAt: request.leaseExpiresAt,\n updatedAt: request.now,\n },\n $inc: { attempts: 1 },\n },\n { returnDocument: 'after' },\n );\n return leased ?? undefined;\n }\n\n /** Puts a delivery that was leased a moment ago back exactly as it was selected. */\n async #restore(selected: DeliveryDocument, leased: DeliveryDocument): Promise<void> {\n const state = {\n status: selected.status,\n attempts: selected.attempts,\n dueAt: selected.dueAt!,\n updatedAt: selected.updatedAt,\n };\n await this.#deliveries.updateOne(\n { _id: leased._id, status: 'processing', leaseToken: leased.leaseToken! },\n selected.status === 'processing'\n ? {\n $set: {\n ...state,\n leaseOwner: selected.leaseOwner!,\n leaseToken: selected.leaseToken!,\n leaseExpiresAt: selected.leaseExpiresAt!,\n },\n }\n : { $set: state, $unset: LEASE_FIELDS },\n );\n }\n\n /** Sequence of the lowest unfinished delivery of the handler and key before `sequence`, if any. */\n async #findUnfinishedPredecessor(\n handler: string,\n key: string,\n sequence: number,\n ): Promise<number | undefined> {\n const predecessor = await this.#deliveries.findOne(\n { handler, key, sequence: { $lt: sequence }, dueAt: { $exists: true } },\n { sort: { sequence: 1 }, projection: { sequence: 1 } },\n );\n return predecessor?.sequence;\n }\n\n /** Whether some delivery of the handler and key runs under a lease that has not expired. */\n async #hasLiveLease(handler: string, key: string, now: Date): Promise<boolean> {\n const running = await this.#deliveries.findOne(\n { handler, key, status: 'processing', dueAt: { $gt: now } },\n { projection: { _id: 1 } },\n );\n return running !== null;\n }\n\n /**\n * Parks pending deliveries that waited behind an unfinished predecessor, which\n * removes them from the claim index until their turn. Parking is a hint, not a\n * guarantee: a predecessor that finishes meanwhile is found by the next\n * {@link MongoEventStore.claim}, which moves the lowest parked delivery back.\n */\n async #parkDeliveries(deliveryIds: readonly string[]): Promise<void> {\n for (let offset = 0; offset < deliveryIds.length; offset += PARK_UPDATE_CHUNK_SIZE) {\n await this.#deliveries.updateMany(\n {\n _id: { $in: deliveryIds.slice(offset, offset + PARK_UPDATE_CHUNK_SIZE) },\n status: 'pending',\n lane: 'ready',\n },\n { $set: { lane: 'parked' } },\n );\n }\n }\n\n /**\n * Moves the lowest parked delivery of every parked key of `handlers` back into\n * the claim index when nothing unfinished precedes it. Level-triggered on\n * purpose: it looks at the current state only, so a crash anywhere, or a\n * predecessor finishing while its followers were being parked, can delay a key\n * until the next claim but never strand it.\n */\n async #unparkNextDeliveries(handlers: readonly string[]): Promise<void> {\n const anyParked = await this.#deliveries.findOne(\n { handler: { $in: [...handlers] }, lane: 'parked' },\n // The sort lets the planner pick the small partial index over the handler's whole history.\n { sort: { handler: 1, key: 1, sequence: 1 }, projection: { _id: 1 } },\n );\n if (anyParked === null) {\n return;\n }\n for (const handler of new Set(handlers)) {\n let afterKey: string | undefined;\n for (;;) {\n const lowest = await this.#deliveries.findOne(\n {\n handler,\n lane: 'parked',\n ...(afterKey === undefined ? {} : { key: { $gt: afterKey } }),\n },\n { sort: { key: 1, sequence: 1 }, projection: { key: 1, sequence: 1 } },\n );\n if (lowest === null) {\n break;\n }\n afterKey = lowest.key!;\n if (\n (await this.#findUnfinishedPredecessor(handler, afterKey, lowest.sequence!)) === undefined\n ) {\n await this.#deliveries.updateOne(\n { _id: lowest._id, lane: 'parked' },\n { $set: { lane: 'ready' } },\n );\n }\n }\n }\n }\n\n async #toClaimedDeliveries(\n leased: readonly DeliveryDocument[],\n leaseExpiresAt: Date,\n ): Promise<ClaimedDelivery[]> {\n const events = await this.#readEnvelopes(leased.map((document) => document.eventId));\n return leased.map((document) => ({\n deliveryId: document._id,\n leaseToken: document.leaseToken!,\n handler: document.handler,\n attempt: document.attempts,\n leaseExpiresAt,\n event: events.get(document.eventId)!,\n }));\n }\n\n async #readEnvelopes(eventIds: readonly string[]): Promise<Map<string, EventEnvelope>> {\n const documents = await this.#events.find({ _id: { $in: [...new Set(eventIds)] } }).toArray();\n return new Map(documents.map((document) => [document._id, toEnvelope(document)]));\n }\n\n async #updateLeased(\n lease: LeaseReference,\n session: ClientSession | undefined,\n update: UpdateFilter<DeliveryDocument>,\n ): Promise<boolean> {\n const result = await this.#deliveries.updateOne(\n { _id: lease.deliveryId, status: 'processing', leaseToken: lease.leaseToken },\n update,\n session === undefined ? {} : { session },\n );\n // Matched, not modified: a repeated renewal with identical values changes nothing but still holds the lease.\n return result.matchedCount === 1;\n }\n\n /**\n * Deletes batches of matching deliveries together with the events no delivery\n * references any more, each batch in one transaction, so a crash can never\n * leave an event without deliveries behind. An append adding a delivery to the\n * same event writes the event document, so the two conflict and one restarts\n * instead of leaving a delivery without event. A delivery requeued since the\n * batch was read conflicts with its deletion and is read again.\n */\n async #purgeMatching(filter: Filter<DeliveryDocument>): Promise<PurgeResult> {\n let deletedDeliveries = 0;\n let deletedEvents = 0;\n for (;;) {\n const step = await this.transaction(async (session) => {\n const batch = await this.#deliveries\n .find(filter, { session, projection: { eventId: 1 }, limit: this.#purgeBatchSize })\n .toArray();\n const eventIds = [...new Set(batch.map((document) => document.eventId))];\n const deliveries = await this.#deliveries.deleteMany(\n { _id: { $in: batch.map((document) => document._id) } },\n { session },\n );\n const stillReferenced = new Set(\n (\n await this.#deliveries\n .find({ eventId: { $in: eventIds } }, { session, projection: { eventId: 1 } })\n .toArray()\n ).map((document) => document.eventId),\n );\n const events = await this.#events.deleteMany(\n { _id: { $in: eventIds.filter((eventId) => !stillReferenced.has(eventId)) } },\n { session },\n );\n return {\n batchSize: batch.length,\n deletedDeliveries: deliveries.deletedCount,\n deletedEvents: events.deletedCount,\n };\n });\n deletedDeliveries += step.deletedDeliveries;\n deletedEvents += step.deletedEvents;\n if (step.batchSize < this.#purgeBatchSize) {\n return { deletedDeliveries, deletedEvents };\n }\n }\n }\n}\n\nfunction deliveryPairKey(eventId: string, handler: string): string {\n return `${eventId}\\u0000${handler}`;\n}\n\nfunction assertInTransaction(session: ClientSession, operation: string): void {\n if (!session.inTransaction()) {\n throw new ConfigurationError(\n `MongoEventStore.${operation} needs a ClientSession inside a started transaction (session.withTransaction or startTransaction). Without one, MongoDB commits each write immediately and the write is no longer atomic with yours`,\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lanes.ts","../src/documents.ts","../src/mongo-errors.ts","../src/mongo-store-state.ts","../src/mongo-append.ts","../src/claim-scan.ts","../src/mongo-claim.ts","../src/mongo-completion.ts","../src/mongo-lane-leases.ts","../src/mongo-ordering.ts","../src/mongo-purge.ts","../src/mongo-queries.ts","../src/mongo-schema.ts","../src/naming.ts","../src/mongo-event-store.ts"],"names":["EventValidationError","ConfigurationError","assertPositiveInteger","createUuidV7"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Number of lanes. Every delivery belongs to one of them, and workers lease\n * whole lanes instead of single deliveries. Same value as in the PostgreSQL store.\n */\nexport const LANE_COUNT = 256;\n\nconst FNV_OFFSET_BASIS = 0x811c9dc5;\nconst FNV_PRIME = 0x01000193;\nconst utf8 = new TextEncoder();\n\n/**\n * Lane of a delivery: the 32-bit FNV-1a hash of the UTF-8 bytes of its\n * ordering key, or of its event id when the event has no key, reduced to\n * `0..LANE_COUNT - 1`. All deliveries of one key therefore share a lane and\n * are owned by one worker at a time, which is what keeps their order. The\n * function is pure and platform independent, so every process agrees on it.\n */\nexport function laneOf(key: string | null, eventId: string): number {\n let hash = FNV_OFFSET_BASIS;\n for (const byte of utf8.encode(key ?? eventId)) {\n hash = Math.imul(hash ^ byte, FNV_PRIME);\n }\n return hash & (LANE_COUNT - 1);\n}\n\n/**\n * The claim a lease token names: the lane, the epoch the lane had, and the\n * claim generation the delivery had when it was claimed.\n */\nexport interface LaneLease {\n readonly laneId: number;\n readonly epoch: number;\n /**\n * Claim generation of the delivery. It grows whenever a claim of the delivery\n * ends (retry, release, burial, lost lease), so a lease of an earlier claim\n * never matches a later claim of the same delivery in the same lane epoch.\n */\n readonly claims: number;\n}\n\n/**\n * The fencing token of a claimed delivery: `<laneId>:<epoch>:<claims>`. Every\n * state change checks the lane epoch and the delivery's claim generation.\n */\nexport function formatLeaseToken(\n laneId: number,\n { epoch, claims }: { readonly epoch: number; readonly claims: number },\n): string {\n return `${laneId}:${epoch}:${claims}`;\n}\n\nconst LEASE_TOKEN_PATTERN = /^(\\d{1,3}):(\\d{1,15}):(\\d{1,15})$/;\n\n/** Splits a lease token; undefined when this store cannot have issued it. */\nexport function parseLeaseToken(token: string): LaneLease | undefined {\n const match = LEASE_TOKEN_PATTERN.exec(token);\n if (match === null || Number(match[1]) >= LANE_COUNT) {\n return undefined;\n }\n return { laneId: Number(match[1]), epoch: Number(match[2]), claims: Number(match[3]) };\n}\n","import {\n EventValidationError,\n type DeliveryRecord,\n type ErrorInfo,\n type EventEnvelope,\n type NewDelivery,\n} from '@relaybus/core';\nimport { laneOf } from './lanes.js';\n\n/** Where a delivery sits relative to the claim index. See {@link DeliveryDocument.lane}. */\nexport type DeliveryLane = 'ready' | 'parked';\n\n/** Shape of a document in the events collection. `_id` is the event id. */\nexport interface EventDocument {\n readonly _id: string;\n readonly type: string;\n readonly source: string;\n /** Ordering key. Absent (or null in documents written before 0.2) for unkeyed events. */\n readonly key?: string | null;\n /** Position among the events of the same key, in commit order. Absent (or null) for unkeyed events. */\n readonly sequence?: number | null;\n /** JSON-normalized payload. Absent when the published payload was `undefined`. */\n readonly payload?: unknown;\n readonly headers: Readonly<Record<string, string>>;\n /** Absent (or null) when the event has none. */\n readonly correlationId?: string | null;\n /** Absent (or null) when the event has none. */\n readonly causationId?: string | null;\n readonly occurredAt: Date;\n /**\n * Incremented when deliveries are added to an already stored event, so a concurrent purge conflicts with\n * it. Absent means 0.\n */\n readonly revision?: number;\n /**\n * Handlers that ever got a delivery of this event, completed ones included.\n * Completed deliveries are deleted, so this list is what keeps a redelivered\n * or republished event from running a completed handler again.\n */\n readonly handlers: readonly string[];\n /** When the event was appended (the caller's clock). Orphaned events older than a purge cutoff are deleted. */\n readonly createdAt: Date;\n /**\n * Latest completion of one of its deliveries. An event nothing references\n * any more is kept as deduplication record until `completedBefore` passes it.\n */\n readonly completedAt?: Date;\n}\n\n/**\n * Status a delivery document can have. Running deliveries are stored as\n * `pending`: whether one runs is derived from its lane (see\n * {@link LaneDocument.inFlight}). `completed` documents only exist when they\n * were left by version 0.1.0, which kept completed deliveries.\n */\nexport type StoredDeliveryStatus = 'pending' | 'dead' | 'completed';\n\n/**\n * Shape of a document in the deliveries collection.\n *\n * `dueAt` exists exactly while the delivery is `pending`, running or not, and\n * equals its `availableAt`. The ordering index is partial on it, so it only\n * ever contains unfinished work. A claim never writes the document.\n *\n * `lane` exists on the same deliveries. A `ready` delivery is in the claim\n * index. A `parked` delivery is a pending, keyed delivery that waited behind an\n * unfinished earlier delivery of its handler and key; the claim index leaves it\n * out so a long queue behind one slow delivery costs nothing per claim. Claims\n * move the lowest parked delivery of a key back to `ready` once nothing\n * unfinished precedes it.\n */\nexport interface DeliveryDocument {\n readonly _id: string;\n readonly eventId: string;\n readonly eventType: string;\n readonly handler: string;\n /** Ordering key. Absent for unkeyed events. */\n readonly key?: string;\n /** Sequence of the event within its key. Absent for unkeyed events. */\n readonly sequence?: number;\n /** Lane the delivery belongs to, see {@link laneOf}. */\n readonly laneId: number;\n readonly status: StoredDeliveryStatus;\n readonly lane?: DeliveryLane;\n /** Attempts that ended: failed, or lost with their lane. A running attempt is not counted yet. */\n readonly attempts: number;\n /**\n * Claim generation: grows when a claim of the delivery ends (retry, release,\n * burial, lost lease). Absent means 0 (documents written before it existed).\n */\n readonly claims?: number;\n /**\n * Lane epoch of the last lost claim charged to the delivery. It only grows, so\n * a repeated or delayed charge of the same or an older lost claim is skipped.\n */\n readonly lostAt?: number;\n readonly availableAt: Date;\n readonly dueAt?: Date;\n readonly lastError?: ErrorInfo;\n readonly createdAt: Date;\n /** Last change after the insert. Absent means `createdAt`: a new delivery is written without it. */\n readonly updatedAt?: Date;\n readonly completedAt?: Date;\n}\n\n/**\n * Shape of a document in the lanes collection, one per lane (`_id` is the lane\n * id). Whoever holds the lane under a live lease is the only claimer that sees\n * its pending deliveries.\n */\nexport interface LaneDocument {\n readonly _id: number;\n /** Fencing token. Grows every time the lane is taken, never when it is freed. */\n readonly epoch: number;\n readonly owner: string | null;\n /**\n * The store instance that holds the lane for `owner`. A process restarted with\n * the same owner name is another instance and does not adopt the lane.\n */\n readonly holder: string | null;\n readonly leaseExpiresAt: Date | null;\n /**\n * Ids of the deliveries the owner claimed. A delivery runs while its\n * document exists as `pending` and its id is listed here. Completed\n * deliveries stay listed (their documents are gone) until the next claim of\n * the lane prunes them, so a completion never writes the lane.\n */\n readonly inFlight: readonly string[];\n /**\n * Deliveries that were in flight when the lane was last taken over. Each of\n * them is charged one attempt before the new holder reads the lane, then the\n * list is cleared.\n */\n readonly lost: readonly LostDelivery[];\n /**\n * Grows with every claim recorded in the lane and every reconciliation of it.\n * A claim records only under the revision it read, so a record that reaches\n * the server after its claim failed and was reconciled changes nothing.\n * Absent means 0.\n */\n readonly revision?: number;\n}\n\n/** A delivery that was in flight when its lane was taken over, and the epoch it was claimed under. */\nexport interface LostDelivery {\n readonly id: string;\n readonly epoch: number;\n}\n\n/** Shape of a document in the completion history (`completionHistory: true`). `_id` is the delivery id. */\nexport interface CompletedDeliveryDocument {\n readonly _id: string;\n readonly eventId: string;\n readonly eventType: string;\n readonly handler: string;\n /** Attempts including the one that completed. */\n readonly attempts: number;\n readonly availableAt: Date;\n readonly createdAt: Date;\n readonly completedAt: Date;\n}\n\n/** Shape of a document in the key sequences collection. `_id` is the ordering key. */\nexport interface KeySequenceDocument {\n readonly _id: string;\n readonly value: number;\n}\n\n/**\n * Builds the stored form of an event. Payload and headers go through JSON so\n * that values JSON cannot represent (Dates, `undefined`, `NaN`) end up exactly\n * as in every other store.\n *\n * @throws EventValidationError when payload or headers contain a lone UTF-16\n * surrogate. BSON strings are UTF-8, so MongoDB would silently store U+FFFD\n * instead and the consumer would read different data than was published.\n */\nexport function toEventDocument(\n event: EventEnvelope,\n {\n sequence,\n handlers,\n createdAt,\n }: {\n readonly sequence: number | null;\n readonly handlers: readonly string[];\n readonly createdAt: Date;\n },\n): EventDocument {\n const payloadJson = serializeWellFormed(event.payload, 'payload');\n const headersJson = serializeWellFormed(event.headers, 'headers')!;\n return {\n _id: event.id,\n type: event.type,\n source: event.source,\n // Fields that are null or 0 are left out: every byte of a new document is written to the oplog too.\n ...(event.key === null ? {} : { key: event.key }),\n ...(sequence === null ? {} : { sequence }),\n ...(payloadJson === undefined ? {} : { payload: JSON.parse(payloadJson) as unknown }),\n headers: JSON.parse(headersJson) as Record<string, string>,\n ...(event.correlationId === null ? {} : { correlationId: event.correlationId }),\n ...(event.causationId === null ? {} : { causationId: event.causationId }),\n occurredAt: event.occurredAt,\n handlers,\n createdAt,\n };\n}\n\n/**\n * JSON.stringify writes a lone surrogate as a `\\udXXX` escape and a valid pair as\n * the character itself, so an escape in that range is exactly a lone surrogate.\n * The lookbehind and the pair group skip escaped backslashes (`\\\\ud800` is text).\n */\nconst LONE_SURROGATE_ESCAPE = /(?<!\\\\)(?:\\\\\\\\)*\\\\ud[89a-f][0-9a-f]{2}/i;\n\nfunction serializeWellFormed(value: unknown, field: string): string | undefined {\n const json = JSON.stringify(value);\n if (json !== undefined && LONE_SURROGATE_ESCAPE.test(json)) {\n throw new EventValidationError(`The event ${field} contains a lone UTF-16 surrogate`, [\n {\n message:\n 'A lone surrogate cannot be stored as UTF-8 and would be replaced by U+FFFD. Remove it or encode the text first (for example with String.prototype.toWellFormed)',\n path: [field],\n },\n ]);\n }\n return json;\n}\n\n/** The envelope stored in an event document. */\nexport function toEnvelope(document: EventDocument): EventEnvelope {\n return {\n id: document._id,\n type: document.type,\n source: document.source,\n key: document.key ?? null,\n payload: document.payload,\n headers: document.headers,\n correlationId: document.correlationId ?? null,\n causationId: document.causationId ?? null,\n occurredAt: document.occurredAt,\n };\n}\n\n/** A new pending delivery of `event`, placed in the lane of the event's key (or id). */\nexport function toDeliveryDocument(\n delivery: NewDelivery,\n {\n event,\n ordering,\n now,\n }: {\n readonly event: Pick<EventEnvelope, 'id' | 'type'>;\n readonly ordering: { readonly key: string | null; readonly sequence: number | null };\n readonly now: Date;\n },\n): DeliveryDocument {\n return {\n _id: delivery.id,\n eventId: event.id,\n eventType: event.type,\n handler: delivery.handler,\n ...(ordering.key === null || ordering.sequence === null\n ? {}\n : { key: ordering.key, sequence: ordering.sequence }),\n laneId: laneOf(ordering.key, event.id),\n status: 'pending',\n lane: 'ready',\n attempts: 0,\n // No updatedAt (it equals createdAt): every byte of a new document is written to the oplog too.\n availableAt: delivery.availableAt,\n dueAt: delivery.availableAt,\n createdAt: now,\n };\n}\n\n/**\n * The record of a stored delivery. `runningIn` is the lane lease the delivery\n * runs under, when it runs: it is then reported as `processing`, with its\n * running attempt counted and the lease of its lane.\n */\nexport function toDeliveryRecord(\n document: DeliveryDocument,\n {\n event,\n runningIn,\n }: { readonly event: EventEnvelope; readonly runningIn: LaneDocument | undefined },\n): DeliveryRecord {\n return {\n id: document._id,\n handler: document.handler,\n status: runningIn === undefined ? document.status : 'processing',\n attempts: runningIn === undefined ? document.attempts : document.attempts + 1,\n availableAt: document.availableAt,\n leaseOwner: runningIn === undefined ? null : runningIn.owner,\n leaseExpiresAt: runningIn === undefined ? null : runningIn.leaseExpiresAt,\n lastError: document.lastError === undefined ? null : toErrorInfo(document.lastError),\n createdAt: document.createdAt,\n updatedAt: document.updatedAt ?? document.createdAt,\n completedAt: document.completedAt ?? null,\n event,\n };\n}\n\n/** The record of a completed delivery kept in the completion history. */\nexport function toCompletedDeliveryRecord(\n document: CompletedDeliveryDocument,\n event: EventEnvelope,\n): DeliveryRecord {\n return {\n id: document._id,\n handler: document.handler,\n status: 'completed',\n attempts: document.attempts,\n availableAt: document.availableAt,\n leaseOwner: null,\n leaseExpiresAt: null,\n lastError: null,\n createdAt: document.createdAt,\n updatedAt: document.completedAt,\n completedAt: document.completedAt,\n event,\n };\n}\n\n/** The completion history entry of a delivery completed at `completedAt`. */\nexport function toCompletedDeliveryDocument(\n document: DeliveryDocument,\n completedAt: Date,\n): CompletedDeliveryDocument {\n return {\n _id: document._id,\n eventId: document.eventId,\n eventType: document.eventType,\n handler: document.handler,\n attempts: document.attempts + 1,\n availableAt: document.availableAt,\n createdAt: document.createdAt,\n completedAt,\n };\n}\n\n/** Copies an error without `undefined` members, which BSON would store as null. */\nexport function toErrorInfo(error: ErrorInfo): ErrorInfo {\n const info: { name: string; message: string; stack?: string; code?: string } = {\n name: error.name,\n message: error.message,\n };\n if (error.stack !== undefined) {\n info.stack = error.stack;\n }\n if (error.code !== undefined) {\n info.code = error.code;\n }\n return info;\n}\n","import { ConfigurationError } from '@relaybus/core';\n\nconst ILLEGAL_OPERATION = 20;\n\n/** True for the server error raised when a transaction runs on a standalone mongod. */\nexport function isTransactionsUnsupportedError(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === ILLEGAL_OPERATION &&\n 'message' in error &&\n typeof error.message === 'string' &&\n error.message.includes('replica set member or mongos')\n );\n}\n\nexport function createTransactionsUnsupportedError(cause: unknown): ConfigurationError {\n return new ConfigurationError(\n 'MongoEventStore needs multi-document transactions, which MongoDB only offers on a replica set or a sharded cluster. Run a single-node replica set for development (mongod --replSet rs0, then rs.initiate())',\n { cause },\n );\n}\n","import { ConfigurationError, type RelayBusLogger } from '@relaybus/core';\nimport type { ClientSession, Collection, Db, MongoClient, TransactionOptions } from 'mongodb';\nimport {\n type CompletedDeliveryDocument,\n type DeliveryDocument,\n type EventDocument,\n type KeySequenceDocument,\n type LaneDocument,\n} from './documents.js';\nimport {\n createTransactionsUnsupportedError,\n isTransactionsUnsupportedError,\n} from './mongo-errors.js';\n\n/** A lane a claim holds: already held before it, or taken by it. */\nexport interface ScopeLane {\n readonly laneId: number;\n /** Epoch of this owner's lease. */\n readonly epoch: number;\n /** `inFlight` of the lane as the claim read it: deliveries this owner claimed earlier. */\n readonly listed: readonly string[];\n /** `revision` of the lane as the claim read it; the record only applies while it is unchanged. */\n readonly revision: number;\n}\n\n/** A claim this store instance handed out and has not seen settled. */\nexport interface HandedOutClaim {\n readonly deliveryId: string;\n readonly owner: string;\n readonly laneId: number;\n readonly epoch: number;\n}\n\n/** The collections, settings and per-instance bookkeeping every part of {@link MongoEventStore} shares. */\nexport type MongoStoreState = {\n readonly client: MongoClient;\n readonly database: Db;\n readonly events: Collection<EventDocument>;\n readonly deliveries: Collection<DeliveryDocument>;\n readonly keySequences: Collection<KeySequenceDocument>;\n readonly lanes: Collection<LaneDocument>;\n readonly completions: Collection<CompletedDeliveryDocument>;\n readonly completionHistory: boolean;\n readonly transactionOptions: TransactionOptions;\n readonly purgeBatchSize: number;\n readonly logger: RelayBusLogger;\n /**\n * Identifies this store instance in the lanes it holds. A process that restarts\n * with the same `leaseOwner` gets a new instance, so it never mistakes the\n * lanes of its dead predecessor for its own: it waits for their leases to\n * expire and takes them over like any other worker.\n */\n readonly instanceId: string;\n /** The last claim of each owner still running on this instance; the next one waits for it. */\n readonly claimsInProgress: Map<string, Promise<unknown>>;\n /**\n * Claims this instance handed out that are not settled yet, keyed by\n * {@link leaseKey} (delivery id and exact lease token), with the owner. A\n * claim is settled when a completion, retry, release or burial of exactly\n * that lease returned, or, for a completion inside the caller's transaction\n * (which may still retry or roll back), when a later claim of the owner finds\n * the delivery gone. After a failed claim, a listed delivery stays listed only\n * if one of these is its current claim (current lane epoch and claim generation).\n */\n readonly handedOut: Map<string, HandedOutClaim>;\n /** Owners whose lanes on this instance still need reconciling after a failed claim. */\n readonly unreconciledOwners: Set<string>;\n};\n\n/** Runs `work` in a transaction on a new session; see {@link MongoEventStore.transaction}. */\nexport async function runInTransaction<T>(\n state: MongoStoreState,\n work: (transaction: ClientSession) => Promise<T>,\n): Promise<T> {\n return runInTransactionWith(state, { work, transactionOptions: state.transactionOptions });\n}\n\n/**\n * Runs `work` in a transaction whose commit the server bounds with `maxCommitTimeMS = timeoutMs`.\n * The driver's `timeoutMS` is deliberately not set on `withTransaction`: it would make every\n * operation that passes its own `timeoutMS` with the session throw. The bus rolls back a\n * transaction that ran past the budget before its commit.\n */\nexport async function runInBudgetedTransaction<T>(\n state: MongoStoreState,\n {\n work,\n timeoutMs,\n }: { readonly work: (transaction: ClientSession) => Promise<T>; readonly timeoutMs: number },\n): Promise<T> {\n const budget = Math.ceil(timeoutMs);\n return runInTransactionWith(state, {\n work,\n transactionOptions: { ...state.transactionOptions, maxCommitTimeMS: budget },\n });\n}\n\nasync function runInTransactionWith<T>(\n state: MongoStoreState,\n {\n work,\n transactionOptions,\n }: {\n readonly work: (transaction: ClientSession) => Promise<T>;\n readonly transactionOptions: TransactionOptions;\n },\n): Promise<T> {\n try {\n return await state.client.withSession(async (session) => {\n let result!: T;\n await session.withTransaction(async () => {\n result = await work(session);\n }, transactionOptions);\n return result;\n });\n } catch (error) {\n if (isTransactionsUnsupportedError(error)) {\n throw createTransactionsUnsupportedError(error);\n }\n throw error;\n }\n}\n\n/** Key of a handed-out claim: the delivery and the exact lease token it was handed out with. */\nexport function leaseKey(deliveryId: string, leaseToken: string): string {\n return `${deliveryId}\\u0000${leaseToken}`;\n}\n\nexport function assertInTransaction(session: ClientSession, operation: string): void {\n if (!session.inTransaction()) {\n throw new ConfigurationError(\n `MongoEventStore.${operation} needs a ClientSession inside a started transaction (session.withTransaction or startTransaction). Without one, MongoDB commits each write immediately and the write is no longer atomic with yours`,\n );\n }\n}\n\n/** Matches a counter (claim generation, lane revision) equal to `count`; a missing counter is 0. */\nexport function atCount(count: number): number | { $not: { $gt: number } } {\n // Counters are never negative, so \"not above 0\" is 0 or absent.\n return count === 0 ? { $not: { $gt: 0 } } : count;\n}\n","import type { AppendEntry, AppendResult, EventEnvelope } from '@relaybus/core';\nimport type { ClientSession, WithId } from 'mongodb';\nimport {\n toDeliveryDocument,\n toEventDocument,\n type DeliveryDocument,\n type EventDocument,\n} from './documents.js';\nimport { assertInTransaction, type MongoStoreState } from './mongo-store-state.js';\n\n/** The events of an append that already existed, with what the append needs of them. */\ntype StoredEvents = Map<string, WithId<EventDocument>>;\n\ntype PlanAppendInput = {\n readonly session: ClientSession;\n readonly entries: readonly AppendEntry[];\n readonly storedEvents: StoredEvents;\n readonly now: Date;\n};\n\n/** What an append writes and reports. */\ntype AppendWritePlan = {\n readonly appendedEventIds: string[];\n readonly duplicateEventIds: string[];\n readonly newEvents: ReadonlyArray<{\n readonly event: EventEnvelope;\n readonly sequence: number | null;\n }>;\n readonly newDeliveries: DeliveryDocument[];\n /** Handlers this call adds, per event. */\n readonly addedHandlers: Map<string, string[]>;\n};\n\ntype WriteAppendInput = {\n readonly session: ClientSession;\n readonly plan: AppendWritePlan;\n readonly storedEvents: StoredEvents;\n readonly now: Date;\n};\n\n/** Appends events and their deliveries inside the caller's transaction. */\nexport class MongoAppend {\n readonly #state: MongoStoreState;\n\n constructor(state: MongoStoreState) {\n this.#state = state;\n }\n\n /** Implements {@link MongoEventStore.append}. */\n async append(\n session: ClientSession,\n { entries, now }: { readonly entries: readonly AppendEntry[]; readonly now: Date },\n ): Promise<AppendResult> {\n assertInTransaction(session, 'append');\n const eventIds = [...new Set(entries.map((entry) => entry.event.id))];\n const storedEvents: StoredEvents = new Map(\n (\n await this.#state.events\n .find(\n { _id: { $in: eventIds } },\n { session, projection: { key: 1, sequence: 1, handlers: 1 } },\n )\n .toArray()\n ).map((stored) => [stored._id, stored]),\n );\n\n const plan = await this.#planAppend({ session, entries, storedEvents, now });\n await this.#writeAppend({ session, plan, storedEvents, now });\n return {\n appendedEventIds: plan.appendedEventIds,\n duplicateEventIds: plan.duplicateEventIds,\n appendedDeliveryCount: plan.newDeliveries.length,\n };\n }\n\n /**\n * Decides, in entry order, which events are new (taking their key sequence) and which deliveries\n * each event still lacks.\n */\n async #planAppend(input: PlanAppendInput): Promise<AppendWritePlan> {\n const { session, entries, storedEvents, now } = input;\n const appendedEventIds: string[] = [];\n const duplicateEventIds: string[] = [];\n const newEvents: Array<{ readonly event: EventEnvelope; readonly sequence: number | null }> =\n [];\n const newDeliveries: DeliveryDocument[] = [];\n /** Handlers every event of the call has, or gets in this call. */\n const knownHandlers = new Map<string, Set<string>>();\n /** Handlers this call adds, per event. */\n const addedHandlers = new Map<string, string[]>();\n const orderingByEventId = new Map<\n string,\n { readonly key: string | null; readonly sequence: number | null }\n >();\n for (const [eventId, stored] of storedEvents) {\n orderingByEventId.set(eventId, {\n key: stored.key ?? null,\n sequence: stored.sequence ?? null,\n });\n knownHandlers.set(eventId, new Set(stored.handlers));\n }\n\n for (const { event, deliveries } of entries) {\n let ordering = orderingByEventId.get(event.id);\n if (ordering === undefined) {\n const sequence = event.key === null ? null : await this.#nextSequence(event.key, session);\n ordering = { key: event.key, sequence };\n orderingByEventId.set(event.id, ordering);\n knownHandlers.set(event.id, new Set());\n newEvents.push({ event, sequence });\n appendedEventIds.push(event.id);\n } else {\n duplicateEventIds.push(event.id);\n }\n const handlers = knownHandlers.get(event.id)!;\n for (const delivery of deliveries) {\n if (handlers.has(delivery.handler)) {\n continue;\n }\n handlers.add(delivery.handler);\n addedHandlers.set(event.id, [...(addedHandlers.get(event.id) ?? []), delivery.handler]);\n newDeliveries.push(toDeliveryDocument(delivery, { event, ordering, now }));\n }\n }\n return { appendedEventIds, duplicateEventIds, newEvents, newDeliveries, addedHandlers };\n }\n\n /** Writes the new events, the handlers added to existing events and the new deliveries, in that order. */\n async #writeAppend(input: WriteAppendInput): Promise<void> {\n const { session, plan, storedEvents, now } = input;\n const { newEvents, newDeliveries, addedHandlers } = plan;\n if (newEvents.length > 0) {\n // Upserts, not inserts: a duplicate-key error would abort the whole transaction,\n // whereas a concurrent writer of the same id surfaces as a retryable write conflict.\n await this.#state.events.bulkWrite(\n newEvents.map(({ event, sequence }) => {\n const document = toEventDocument(event, {\n sequence,\n handlers: addedHandlers.get(event.id) ?? [],\n createdAt: now,\n });\n return {\n updateOne: {\n filter: { _id: document._id },\n update: { $setOnInsert: document },\n upsert: true,\n },\n };\n }),\n { session, ordered: true },\n );\n }\n const extendedEvents = [...addedHandlers].filter(([eventId]) => storedEvents.has(eventId));\n if (extendedEvents.length > 0) {\n await this.#state.events.bulkWrite(\n extendedEvents.map(([eventId, handlers]) => ({\n updateOne: {\n filter: { _id: eventId },\n update: { $inc: { revision: 1 }, $push: { handlers: { $each: handlers } } },\n },\n })),\n { session, ordered: true },\n );\n }\n if (newDeliveries.length > 0) {\n await this.#state.deliveries.bulkWrite(\n newDeliveries.map((document) => ({\n updateOne: {\n filter: { eventId: document.eventId, handler: document.handler },\n update: { $setOnInsert: document },\n upsert: true,\n },\n })),\n { session, ordered: true },\n );\n }\n }\n\n /** Atomically increments the counter of `key`; conflicting appends of the key serialize here. */\n async #nextSequence(key: string, session: ClientSession): Promise<number> {\n const counter = await this.#state.keySequences.findOneAndUpdate(\n { _id: key },\n { $inc: { value: 1 } },\n { upsert: true, returnDocument: 'after', session },\n );\n return counter!.value;\n }\n}\n","/** What one claim call has learned about the deliveries of a single handler and key. */\ninterface KeyKnowledge {\n /** Lowest sequence known to be unfinished. Every later delivery of the key must wait. */\n openSequence: number | undefined;\n /** Pending deliveries that waited behind `openSequence`, candidates for parking. */\n waiting: string[];\n /** Lane of the key (all deliveries of a key share one). Undefined until a delivery waited. */\n laneId: number | undefined;\n}\n\n/**\n * Bookkeeping of one claim call. A claim scans due deliveries in due order and\n * meets many deliveries of the same key; what it learns about a key from the\n * database once (its lowest unfinished delivery) answers every later delivery\n * of that key without another query.\n */\nexport class ClaimScan {\n readonly #keys = new Map<string, KeyKnowledge>();\n\n /** Whether an unfinished delivery this scan knows of comes before the delivery with `sequence`. */\n waits(orderingId: string, sequence: number): boolean {\n const known = this.#keys.get(orderingId);\n return known?.openSequence !== undefined && sequence > known.openSequence;\n }\n\n /** Whether this scan already learned anything about the key. */\n knows(orderingId: string): boolean {\n return this.#keys.has(orderingId);\n }\n\n /** Records an unfinished delivery of the key with this sequence. */\n noteOpen(orderingId: string, sequence: number): void {\n const known = this.#know(orderingId);\n known.openSequence = Math.min(known.openSequence ?? sequence, sequence);\n }\n\n /** Remembers a pending delivery of lane `laneId` that waited behind an unfinished predecessor. */\n noteWaiting(\n orderingId: string,\n { deliveryId, laneId }: { readonly deliveryId: string; readonly laneId: number },\n ): void {\n const known = this.#know(orderingId);\n known.waiting.push(deliveryId);\n known.laneId = laneId;\n }\n\n /**\n * Ids of the waiting deliveries of every key that accumulated at least\n * `minimum` of them, or that lives in one of `handedBack`. Shorter queues\n * of a lane that stays held remain in the claim index: moving them out and\n * back would cost more than skipping them. In a lane handed back they are\n * all its due work, and leaving them ready would make every later claim take\n * the lane for nothing.\n */\n waitingBacklogs(minimum: number, handedBack: ReadonlySet<number>): string[] {\n return [...this.#keys.values()]\n .filter((known) => known.waiting.length >= minimum || handedBack.has(known.laneId!))\n .flatMap((known) => known.waiting);\n }\n\n #know(orderingId: string): KeyKnowledge {\n let known = this.#keys.get(orderingId);\n if (known === undefined) {\n known = { openSequence: undefined, waiting: [], laneId: undefined };\n this.#keys.set(orderingId, known);\n }\n return known;\n }\n}\n\n/** Identity of the ordering of a handler and key. */\nexport function orderingIdentity(handler: string, key: string): string {\n return `${handler}\\u0000${key}`;\n}\n","import type { ClaimRequest, ClaimedDelivery } from '@relaybus/core';\nimport { ClaimScan, orderingIdentity } from './claim-scan.js';\nimport type { DeliveryDocument, LaneDocument } from './documents.js';\nimport { formatLeaseToken, parseLeaseToken } from './lanes.js';\nimport type { MongoLaneLeases } from './mongo-lane-leases.js';\nimport type { MongoOrdering } from './mongo-ordering.js';\nimport type { MongoQueries } from './mongo-queries.js';\nimport {\n leaseKey,\n runInTransaction,\n type MongoStoreState,\n type ScopeLane,\n} from './mongo-store-state.js';\n\n/** Deliveries that waited behind one unfinished predecessor before they are parked. */\nconst PARK_BACKLOG_THRESHOLD = 32;\n\n/** Lanes a claim takes in its first round; every further round takes twice as many. */\nconst INITIAL_LANES_PER_ROUND = 4;\n\n/**\n * Lanes one candidate query covers. A query over more lanes than the planner\n * explodes into merged index scans (200 by default) would sort every due\n * delivery of those lanes in memory instead of reading them in due order.\n */\nconst LANES_PER_CANDIDATE_QUERY = 128;\n\n/** The deliveries the held lanes still run: their ids and (handler, key) identities. */\ntype RunningDeliveries = { readonly ids: Set<string>; readonly keys: Set<string> };\n\n/** One claim's lanes and picks while it reads candidates. */\ntype PickAcrossLanesInput = {\n readonly request: ClaimRequest;\n /** Grows by every lane the claim takes. */\n readonly scope: Map<number, ScopeLane>;\n readonly scan: ClaimScan;\n readonly running: Promise<RunningDeliveries>;\n readonly picked: DeliveryDocument[];\n};\n\n/** The held lanes as the claim read them. */\nfunction scopeOf(held: readonly LaneDocument[]): Map<number, ScopeLane> {\n return new Map<number, ScopeLane>(\n held.map((lane) => [\n lane._id,\n {\n laneId: lane._id,\n epoch: lane.epoch,\n listed: lane.inFlight,\n revision: lane.revision ?? 0,\n },\n ]),\n );\n}\n\n/** Claims due deliveries for one owner at a time and reconciles the lanes after a failed claim. */\nexport class MongoClaims {\n readonly #state: MongoStoreState;\n readonly #laneLeases: MongoLaneLeases;\n readonly #ordering: MongoOrdering;\n readonly #queries: MongoQueries;\n\n constructor(\n state: MongoStoreState,\n collaborators: {\n readonly laneLeases: MongoLaneLeases;\n readonly ordering: MongoOrdering;\n readonly queries: MongoQueries;\n },\n ) {\n this.#state = state;\n this.#laneLeases = collaborators.laneLeases;\n this.#ordering = collaborators.ordering;\n this.#queries = collaborators.queries;\n }\n\n /** Implements {@link MongoEventStore.claim}. */\n async claim(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n if (request.handlers.length === 0 || request.limit <= 0) {\n return [];\n }\n // Claims of one owner read the same held lanes and in-flight lists, so they must not overlap\n // (bus.runOnce() next to a running dispatcher, for instance): they run one after the other.\n const owner = request.leaseOwner;\n const previous = this.#state.claimsInProgress.get(owner) ?? Promise.resolve();\n const claimed = previous.then(() => this.#claimReconciled(request));\n const settled = Promise.allSettled([claimed]);\n this.#state.claimsInProgress.set(owner, settled);\n void settled.then(() => {\n if (this.#state.claimsInProgress.get(owner) === settled) {\n this.#state.claimsInProgress.delete(owner);\n }\n });\n return claimed;\n }\n\n /**\n * Runs one claim and remembers what it hands out. When the claim fails at any\n * point, also after its record reached the database without the reply\n * reaching this process, the lanes this owner holds on this instance are\n * reconciled: every listed delivery this instance has not handed out, or has\n * handed out and seen settled, is taken out of them, so nothing stays listed\n * as running that nobody runs.\n */\n async #claimReconciled(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n const owner = request.leaseOwner;\n if (this.#state.unreconciledOwners.has(owner)) {\n // An earlier reconciliation failed: a delivery may still be listed that nobody runs, and the\n // owner's other deliveries may keep the lane alive, so it is done before claiming anything.\n await this.#reconcileLanes(owner);\n this.#state.unreconciledOwners.delete(owner);\n }\n try {\n const claimed = await this.#claimNow(request);\n for (const delivery of claimed) {\n const { laneId, epoch } = parseLeaseToken(delivery.leaseToken)!;\n this.#state.handedOut.set(leaseKey(delivery.deliveryId, delivery.leaseToken), {\n deliveryId: delivery.deliveryId,\n owner: request.leaseOwner,\n laneId,\n epoch,\n });\n }\n return claimed;\n } catch (error) {\n const [reconciled] = await Promise.allSettled([this.#reconcileLanes(owner)]);\n if (reconciled.status === 'rejected') {\n this.#state.unreconciledOwners.add(owner);\n }\n throw error;\n }\n }\n\n /**\n * Takes every delivery this instance does not run out of the lanes `owner`\n * holds on it: every listed delivery whose current claim (lane epoch and\n * claim generation now) was not handed out by this instance, or was settled.\n * One transaction, and the lanes are written first under their epoch and\n * holder: a worker taking a lane over meanwhile conflicts with it, so its\n * claim is never touched. The claim generation of every delivery taken out\n * moves on, so no lease of those claims (a completion that failed and is\n * retried later, say) can ever match a later claim of the same delivery.\n * Registrations of this owner that are not the current claim of a listed\n * delivery are dropped.\n */\n async #reconcileLanes(owner: string): Promise<void> {\n await runInTransaction(this.#state, async (session) => {\n const held = await this.#state.lanes\n .find({ owner, holder: this.#state.instanceId }, { session })\n .toArray();\n const listed = held.flatMap((lane) => lane.inFlight);\n const claimsById = new Map(\n (\n await this.#state.deliveries\n .find(\n { _id: { $in: listed }, status: 'pending' },\n { session, projection: { claims: 1 } },\n )\n .toArray()\n ).map((document) => [document._id, document.claims ?? 0]),\n );\n const current = new Set<string>();\n const unclaimed = held.map((lane) => ({\n lane,\n ids: lane.inFlight.filter((id) => {\n const key = leaseKey(\n id,\n formatLeaseToken(lane._id, { epoch: lane.epoch, claims: claimsById.get(id) ?? 0 }),\n );\n current.add(key);\n return !this.#state.handedOut.has(key);\n }),\n }));\n for (const [key, entry] of this.#state.handedOut) {\n if (entry.owner === owner && !current.has(key)) {\n this.#state.handedOut.delete(key);\n }\n }\n if (held.length === 0) {\n return;\n }\n // Every lane gets a new revision, also one with nothing to take out: a record of the failed\n // claim that is still on its way to the server then matches nothing when it arrives.\n await this.#state.lanes.bulkWrite(\n unclaimed.map(({ lane, ids }) => ({\n updateOne: {\n filter: { _id: lane._id, epoch: lane.epoch, holder: this.#state.instanceId },\n update: { $pull: { inFlight: { $in: ids } }, $inc: { revision: 1 } },\n },\n })),\n { session, ordered: false },\n );\n await this.#state.deliveries.updateMany(\n { _id: { $in: unclaimed.flatMap((entry) => entry.ids) }, status: 'pending' },\n { $inc: { claims: 1 } },\n { session },\n );\n });\n }\n\n async #claimNow(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n // Independent reads, so they share one round trip: unparking only has to finish before candidates are read.\n const [held] = await Promise.all([\n this.#state.lanes\n .find({\n owner: request.leaseOwner,\n holder: this.#state.instanceId,\n leaseExpiresAt: { $gt: request.now },\n })\n .toArray(),\n this.#ordering.unparkNextDeliveries(request.handlers),\n ]);\n await this.#laneLeases.chargeLost(held);\n const scope = scopeOf(held);\n // Loaded while the first candidates are read; only keyed candidates and the record need it.\n const running = this.#loadRunning(held);\n const scan = new ClaimScan();\n const picked: DeliveryDocument[] = [];\n await this.#pickAcrossLanes({ request, scope, scan, running, picked });\n // Read before recording: a failure from here on must not leave picks listed as running.\n const events = await this.#queries.readEnvelopes(picked.map((document) => document.eventId));\n const runningIds = (await running).ids;\n this.#forgetSettled(held, { runningIds, owner: request.leaseOwner });\n const { recorded, handedBack } = await this.#laneLeases.recordClaim(scope, {\n picked,\n runningIds,\n request,\n });\n const claimed = await this.#releaseOvertaken(\n picked.filter((document) => recorded.has(document.laneId)),\n scope,\n );\n await this.#ordering.parkWaiting(scan.waitingBacklogs(PARK_BACKLOG_THRESHOLD, handedBack));\n return claimed.map((document) => ({\n deliveryId: document._id,\n leaseToken: formatLeaseToken(document.laneId, {\n epoch: scope.get(document.laneId)!.epoch,\n claims: document.claims ?? 0,\n }),\n handler: document.handler,\n attempt: document.attempts + 1,\n leaseExpiresAt: request.leaseExpiresAt,\n event: events.get(document.eventId)!,\n }));\n }\n\n /** The deliveries still running in the held lanes, with their (handler, key) identities. */\n #loadRunning(held: readonly LaneDocument[]): Promise<RunningDeliveries> {\n return this.#queries.findRunning(held.flatMap((lane) => lane.inFlight)).then((documents) => ({\n ids: new Set(documents.map((document) => document._id)),\n keys: new Set(\n documents.flatMap((document) =>\n document.key === undefined ? [] : [orderingIdentity(document.handler, document.key)],\n ),\n ),\n }));\n }\n\n /**\n * Picks from the lanes in `scope`, then takes free lanes with due work, a few more each round\n * (4, 8, 16, ...), and picks from them, until the claim is full or no free lane is left.\n */\n async #pickAcrossLanes(input: PickAcrossLanesInput): Promise<void> {\n const { request, scope, scan, running, picked } = input;\n const pickFrom = async (lanes: readonly ScopeLane[]): Promise<void> => {\n for (let offset = 0; offset < lanes.length; offset += LANES_PER_CANDIDATE_QUERY) {\n if (picked.length < request.limit) {\n await this.#ordering.pickCandidates({\n lanes: lanes.slice(offset, offset + LANES_PER_CANDIDATE_QUERY),\n request,\n scan,\n running,\n picked,\n });\n }\n }\n };\n await pickFrom([...scope.values()]);\n const passed = new Set(scope.keys());\n for (let laneCount = INITIAL_LANES_PER_ROUND; picked.length < request.limit; laneCount *= 2) {\n const free = await this.#laneLeases.findFreeLanes(request, {\n laneCount,\n passed: [...passed],\n });\n if (free.length === 0) {\n break;\n }\n for (const laneId of free) {\n passed.add(laneId);\n }\n const taken = await this.#laneLeases.takeLanes(free, request);\n for (const lane of taken) {\n scope.set(lane.laneId, lane);\n }\n await pickFrom(taken);\n }\n }\n\n /**\n * Forgets the claims of `owner` that are listed in the held lanes but no longer pending:\n * completed (a burial or retry would have unlisted it). Such a claim is settled, also when it was\n * completed inside a caller's transaction that committed. Only this owner's registrations of the\n * lane epochs it read: the same delivery may meanwhile have been requeued and handed out again,\n * under another owner or lane epoch.\n */\n #forgetSettled(\n held: readonly LaneDocument[],\n { runningIds, owner }: { readonly runningIds: ReadonlySet<string>; readonly owner: string },\n ): void {\n const gone = new Set(\n held.flatMap((lane) =>\n lane.inFlight\n .filter((id) => !runningIds.has(id))\n .map((id) => `${id}\\u0000${lane._id}:${lane.epoch}`),\n ),\n );\n for (const [key, entry] of this.#state.handedOut) {\n if (\n entry.owner === owner &&\n gone.has(`${entry.deliveryId}\\u0000${entry.laneId}:${entry.epoch}`)\n ) {\n this.#state.handedOut.delete(key);\n }\n }\n }\n\n /**\n * Gives back the recorded keyed picks that a delivery requeued during the\n * claim now precedes, without charging an attempt, and returns the rest. The\n * claim checked their predecessors before recording them; a dead letter\n * requeued in between would otherwise wait behind its own successor. Once a\n * pick is recorded, a later requeue waits for it like for any running delivery.\n */\n async #releaseOvertaken(\n claimed: readonly DeliveryDocument[],\n scope: ReadonlyMap<number, ScopeLane>,\n ): Promise<DeliveryDocument[]> {\n const keyed = claimed.filter((document) => document.key !== undefined);\n if (keyed.length === 0) {\n return [...claimed];\n }\n // One query for the whole batch: each branch is one probe of the ordering index.\n const blockers = await this.#state.deliveries\n .find(\n {\n $or: keyed.map((document) => ({\n handler: document.handler,\n key: document.key!,\n sequence: { $lt: document.sequence! },\n dueAt: { $exists: true },\n })),\n },\n { projection: { handler: 1, key: 1 } },\n )\n .toArray();\n const blocked = new Set(\n blockers.map((blocker) => orderingIdentity(blocker.handler, blocker.key!)),\n );\n const overtaken = new Set(\n keyed\n .filter((document) => blocked.has(orderingIdentity(document.handler, document.key!)))\n .map((document) => document._id),\n );\n if (overtaken.size === 0) {\n return [...claimed];\n }\n await this.#releasePicks(\n claimed.filter((document) => overtaken.has(document._id)),\n scope,\n );\n return claimed.filter((document) => !overtaken.has(document._id));\n }\n\n /** Takes recorded picks out of their lanes' in-flight lists again, under the claim's epochs and record revisions. */\n async #releasePicks(\n documents: readonly DeliveryDocument[],\n scope: ReadonlyMap<number, ScopeLane>,\n ): Promise<void> {\n const idsByLane = new Map<number, string[]>();\n for (const document of documents) {\n idsByLane.set(document.laneId, [...(idsByLane.get(document.laneId) ?? []), document._id]);\n }\n await Promise.all(\n [...idsByLane].map(([laneId, ids]) =>\n this.#state.lanes.updateOne(\n // Under the revision the record left: a pull that reaches the server late, after a\n // reconciliation and a newer claim of the same delivery, matches nothing.\n {\n _id: laneId,\n epoch: scope.get(laneId)!.epoch,\n revision: scope.get(laneId)!.revision + 1,\n },\n { $pull: { inFlight: { $in: ids } } },\n ),\n ),\n );\n }\n}\n","import type { ErrorInfo, LeaseReference } from '@relaybus/core';\nimport type { ClientSession, Filter, UpdateFilter } from 'mongodb';\nimport {\n toCompletedDeliveryDocument,\n toErrorInfo,\n type DeliveryDocument,\n type LaneDocument,\n} from './documents.js';\nimport { formatLeaseToken, parseLeaseToken, type LaneLease } from './lanes.js';\nimport {\n assertInTransaction,\n atCount,\n leaseKey,\n runInTransaction,\n type MongoStoreState,\n} from './mongo-store-state.js';\n\n/** Fields that exist only while a delivery is unfinished. */\nconst FINISHED_FIELDS = { dueAt: '', lane: '' } as const;\n\n/** A lease of this store, with the delivery it names. */\ninterface IssuedLease extends LaneLease {\n readonly deliveryId: string;\n}\n\n/** Ends claims: completion, retry, release, burial and lease renewal, all fenced by the lane lease. */\nexport class MongoCompletion {\n readonly #state: MongoStoreState;\n\n constructor(state: MongoStoreState) {\n this.#state = state;\n }\n\n /** Implements {@link MongoEventStore.extendLease}. */\n async extendLease(lease: LeaseReference, leaseExpiresAt: Date): Promise<boolean> {\n const held = parseLeaseToken(lease.leaseToken);\n if (held === undefined) {\n return false;\n }\n const deliveryId = String(lease.deliveryId);\n // One transaction: a stale lease must not extend the lane of a newer claim of the delivery.\n // A claim ending or starting meanwhile writes the delivery or the lane, so the two conflict.\n return runInTransaction(this.#state, async (session) => {\n const running = await this.#state.deliveries.findOne(ofClaim({ ...held, deliveryId }), {\n session,\n projection: { _id: 1 },\n });\n if (running === null) {\n return false;\n }\n const renewed = await this.#state.lanes.updateOne(\n { _id: held.laneId, epoch: held.epoch, inFlight: deliveryId },\n { $max: { leaseExpiresAt } },\n { session },\n );\n return renewed.matchedCount === 1;\n });\n }\n\n /** Implements {@link MongoEventStore.complete}. */\n async complete(\n lease: LeaseReference,\n { now, session }: { readonly now: Date; readonly session?: ClientSession | undefined },\n ): Promise<boolean> {\n if (session !== undefined) {\n assertInTransaction(session, 'complete');\n }\n return (await this.#completeLeases([lease], { now, session }))[0]!;\n }\n\n /** Implements {@link MongoEventStore.completeMany}. */\n completeMany(leases: readonly LeaseReference[], now: Date): Promise<boolean[]> {\n return this.#completeLeases(leases, { now, session: undefined });\n }\n\n /** Implements {@link MongoEventStore.reschedule}. */\n async reschedule(\n lease: LeaseReference,\n {\n availableAt,\n error,\n now,\n }: { readonly availableAt: Date; readonly error: ErrorInfo; readonly now: Date },\n ): Promise<boolean> {\n return this.#leaveFlight(lease, {\n $set: { availableAt, dueAt: availableAt, lastError: toErrorInfo(error), updatedAt: now },\n $inc: { attempts: 1, claims: 1 },\n });\n }\n\n /** Implements {@link MongoEventStore.release}. */\n async release(lease: LeaseReference, now: Date): Promise<boolean> {\n return this.#leaveFlight(lease, {\n $set: { availableAt: now, dueAt: now, updatedAt: now },\n $inc: { claims: 1 },\n });\n }\n\n /** Implements {@link MongoEventStore.bury}. */\n async bury(\n lease: LeaseReference,\n { error, now }: { readonly error: ErrorInfo; readonly now: Date },\n ): Promise<boolean> {\n return this.#leaveFlight(lease, {\n $set: { status: 'dead', lastError: toErrorInfo(error), updatedAt: now },\n $unset: FINISHED_FIELDS,\n $inc: { attempts: 1, claims: 1 },\n });\n }\n\n /**\n * Runs `operation`, which ends the claims of `leases` (completion, retry,\n * release, burial), and once it returned forgets exactly those leases as\n * handed out. When it throws, they stay registered: the caller may retry\n * with the same lease, which must still find its claim.\n */\n async #settle<T>(leases: readonly LeaseReference[], operation: () => Promise<T>): Promise<T> {\n const result = await operation();\n for (const lease of leases) {\n this.#state.handedOut.delete(leaseKey(String(lease.deliveryId), String(lease.leaseToken)));\n }\n return result;\n }\n\n /**\n * Deletes the delivery of every lease whose lane still has the lease's epoch\n * and lists the delivery, in one transaction (the caller's, when given).\n * Returns one flag per lease, in order; a lease listed twice completes once.\n */\n async #completeLeases(\n leases: readonly LeaseReference[],\n { now, session }: { readonly now: Date; readonly session: ClientSession | undefined },\n ): Promise<boolean[]> {\n // Inside the caller's transaction the completion may still be retried or rolled back, so it\n // stays registered until a later claim finds the delivery gone.\n return session === undefined\n ? this.#settle(leases, () => this.#completeIssued(leases, { now, session: undefined }))\n : this.#completeIssued(leases, { now, session });\n }\n\n async #completeIssued(\n leases: readonly LeaseReference[],\n { now, session }: { readonly now: Date; readonly session: ClientSession | undefined },\n ): Promise<boolean[]> {\n const parsed = leases.map((lease) => parseLeaseToken(lease.leaseToken));\n const issued = leases.flatMap((lease, index) =>\n parsed[index] === undefined\n ? []\n : [{ deliveryId: String(lease.deliveryId), ...parsed[index] }],\n );\n let completed = new Set<string>();\n if (issued.length > 0) {\n if (session !== undefined) {\n completed = await this.#deleteCompleted(issued, { now, session });\n } else if (this.#state.completionHistory) {\n completed = await runInTransaction(this.#state, (own) =>\n this.#deleteCompleted(issued, { now, session: own }),\n );\n } else {\n completed = await this.#deleteFenced(issued, now);\n }\n }\n return leases.map(\n (lease, index) =>\n parsed[index] !== undefined &&\n completed.delete(leaseIdentity({ deliveryId: String(lease.deliveryId), ...parsed[index] })),\n );\n }\n\n /**\n * Completion without a transaction, used when no history record has to be\n * written with the deletion. The deliveries' claim generations are read\n * first, then the lanes, and a delivery is deleted only if it still has the\n * lease's generation. A takeover moves the generation of every delivery it\n * takes from the previous owner on before it reads anything, and so do a\n * retry, a release and a burial, so:\n * - a takeover before the delivery read shows up in the lane read (new epoch);\n * - a takeover between the two reads shows up in the lane read as well;\n * - a takeover, retry, release or burial after the lane read changed the\n * generation, so the delete matches nothing.\n * A completion and a takeover (or the end of the claim) therefore never both succeed. Two concurrent\n * completions of the same lease may both report true (the dispatcher never\n * issues them); one call with a lease listed twice reports it once.\n */\n async #deleteFenced(issued: readonly IssuedLease[], now: Date): Promise<Set<string>> {\n const ids = [...new Set(issued.map((lease) => lease.deliveryId))];\n const documents = await this.#state.deliveries\n .find({ _id: { $in: ids }, status: 'pending' }, { projection: { claims: 1, eventId: 1 } })\n .toArray();\n const lanes = new Map(\n (\n await this.#state.lanes\n .find(\n { _id: { $in: [...new Set(issued.map((lease) => lease.laneId))] } },\n { projection: { epoch: 1, inFlight: 1 } },\n )\n .toArray()\n ).map((lane) => [lane._id, lane]),\n );\n const fenced = fencedLeases(issued, { lanes, documents });\n if (fenced.length === 0) {\n return new Set();\n }\n await this.#markEventsCompleted(fenced, { documents, now });\n const deleted = await this.#state.deliveries.deleteMany({ $or: fenced.map(ofClaim) });\n // Each branch of the delete matches at most one document of exactly that claim, so all of\n // them deleting proves every completion. When fewer did, a claim ended or changed hands after\n // it was read, and nothing tells which of them this call deleted: a missing document may as\n // well have been completed by the claim that took it over. Report none, never a guess.\n return deleted.deletedCount === fenced.length\n ? new Set(fenced.map((lease) => leaseIdentity(lease)))\n : new Set();\n }\n\n /**\n * The transactional part of a completion. The lanes are only read: the\n * conflict with a takeover comes from the deleted delivery documents, which a\n * takeover writes before it reads them (see `MongoLaneLeases.takeLanes`).\n * So whichever of the two commits second either fails with a write conflict\n * and is retried against the new state, or waits for the first.\n */\n async #deleteCompleted(\n issued: readonly IssuedLease[],\n { now, session }: { readonly now: Date; readonly session: ClientSession },\n ): Promise<Set<string>> {\n const lanes = new Map(\n (\n await this.#state.lanes\n .find(\n { _id: { $in: [...new Set(issued.map((lease) => lease.laneId))] } },\n { session, projection: { epoch: 1, inFlight: 1 } },\n )\n .toArray()\n ).map((lane) => [lane._id, lane]),\n );\n const documents = await this.#state.deliveries\n .find(\n { _id: { $in: [...new Set(issued.map((lease) => lease.deliveryId))] }, status: 'pending' },\n { session },\n )\n .toArray();\n const fenced = fencedLeases(issued, { lanes, documents });\n if (fenced.length === 0) {\n return new Set();\n }\n await this.#markEventsCompleted(fenced, { documents, now, session });\n await this.#state.deliveries.deleteMany({ $or: fenced.map(ofClaim) }, { session });\n if (this.#state.completionHistory) {\n const completedIds = new Set(fenced.map((lease) => lease.deliveryId));\n await this.#state.completions.insertMany(\n documents\n .filter((document) => completedIds.has(document._id))\n .map((document) => toCompletedDeliveryDocument(document, now)),\n { session },\n );\n }\n return new Set(fenced.map((lease) => leaseIdentity(lease)));\n }\n\n /**\n * Records `now` as the latest completion of the events of the fenced\n * deliveries (`$max`, so an earlier clock never moves it back). Written\n * before the deletion, it can only be later than the real last completion\n * (when the deletion then fails), which keeps the event longer, never shorter.\n * Inside a transaction it is part of it: the transaction may hold the event\n * already (a transactional handler that appended to its own event), and a\n * write from outside would wait for it forever. Deliveries of one event that\n * complete in concurrent transactions (fan-out to transactional handlers)\n * therefore conflict on the event document, and one of them retries.\n */\n async #markEventsCompleted(\n fenced: readonly IssuedLease[],\n {\n documents,\n now,\n session,\n }: {\n readonly documents: readonly Pick<DeliveryDocument, '_id' | 'eventId'>[];\n readonly now: Date;\n readonly session?: ClientSession | undefined;\n },\n ): Promise<void> {\n const completedIds = new Set(fenced.map((lease) => lease.deliveryId));\n const eventIds = [\n ...new Set(\n documents\n .filter((document) => completedIds.has(document._id))\n .map((document) => document.eventId),\n ),\n ];\n await this.#state.events.updateMany(\n { _id: { $in: eventIds } },\n { $max: { completedAt: now } },\n session === undefined ? {} : { session },\n );\n }\n\n /**\n * Applies `update` to a running delivery and takes it out of its lane's\n * in-flight list, if the lane still has the lease's epoch. One transaction:\n * the lane write fences the change against a takeover.\n */\n async #leaveFlight(\n lease: LeaseReference,\n update: UpdateFilter<DeliveryDocument>,\n ): Promise<boolean> {\n const held = parseLeaseToken(lease.leaseToken);\n if (held === undefined) {\n return false;\n }\n const deliveryId = String(lease.deliveryId);\n const ofThisClaim = ofClaim({ ...held, deliveryId });\n return this.#settle([lease], () =>\n this.#leaveFlightNow(held, { deliveryId, ofThisClaim, update }),\n );\n }\n\n async #leaveFlightNow(\n held: LaneLease,\n {\n deliveryId,\n ofThisClaim,\n update,\n }: {\n readonly deliveryId: string;\n readonly ofThisClaim: Filter<DeliveryDocument>;\n readonly update: UpdateFilter<DeliveryDocument>;\n },\n ): Promise<boolean> {\n return runInTransaction(this.#state, async (session) => {\n // The claim generation is checked before the lane is touched: a later claim of the same\n // delivery in the same lane epoch is listed under the same id and must stay listed.\n if (\n (await this.#state.deliveries.findOne(ofThisClaim, { session, projection: { _id: 1 } })) ===\n null\n ) {\n return false;\n }\n const fence = await this.#state.lanes.updateOne(\n { _id: held.laneId, epoch: held.epoch, inFlight: deliveryId },\n { $pull: { inFlight: deliveryId } },\n { session },\n );\n if (fence.matchedCount === 0) {\n return false;\n }\n const changed = await this.#state.deliveries.updateOne(ofThisClaim, update, { session });\n return changed.matchedCount === 1;\n });\n }\n}\n\n/** The leases whose lane still has their epoch and lists the delivery, and whose delivery is still in their claim. */\nfunction fencedLeases(\n issued: readonly IssuedLease[],\n {\n lanes,\n documents,\n }: {\n readonly lanes: ReadonlyMap<number, Pick<LaneDocument, 'epoch' | 'inFlight'>>;\n readonly documents: readonly Pick<DeliveryDocument, '_id' | 'claims'>[];\n },\n): IssuedLease[] {\n const claimsById = new Map(documents.map((document) => [document._id, document.claims ?? 0]));\n const fenced = new Map<string, IssuedLease>();\n for (const lease of issued) {\n const lane = lanes.get(lease.laneId)!;\n if (\n claimsById.get(lease.deliveryId) === lease.claims &&\n lane.epoch === lease.epoch &&\n lane.inFlight.includes(lease.deliveryId)\n ) {\n // A lease listed twice completes once.\n fenced.set(leaseIdentity(lease), lease);\n }\n }\n return [...fenced.values()];\n}\n\n/** The delivery document of exactly this claim, still pending. */\nfunction ofClaim(lease: IssuedLease): Filter<DeliveryDocument> {\n return { _id: lease.deliveryId, status: 'pending', claims: atCount(lease.claims) };\n}\n\nfunction leaseIdentity(lease: IssuedLease): string {\n return `${lease.deliveryId}\\u0000${formatLeaseToken(lease.laneId, { epoch: lease.epoch, claims: lease.claims })}`;\n}\n","import type { ClaimRequest } from '@relaybus/core';\nimport type { AnyBulkWriteOperation } from 'mongodb';\nimport type { DeliveryDocument, LaneDocument } from './documents.js';\nimport type { MongoQueries } from './mongo-queries.js';\nimport { atCount, type MongoStoreState, type ScopeLane } from './mongo-store-state.js';\n\n/** Takes, records and hands back the lanes a claim works in. */\nexport class MongoLaneLeases {\n readonly #state: MongoStoreState;\n readonly #queries: MongoQueries;\n\n constructor(state: MongoStoreState, collaborators: { readonly queries: MongoQueries }) {\n this.#state = state;\n this.#queries = collaborators.queries;\n }\n\n /**\n * Up to `laneCount` lanes nobody holds under a live lease that have a due,\n * ready delivery of the requested handlers, the lane with the oldest such\n * delivery first, leaving out `passed`. One round trip: the oldest delivery\n * of each lane is one index probe on the server. A lane whose due deliveries\n * all wait behind an unfinished predecessor is taken at most once: the claim\n * that hands it back parks them (see `ClaimScan.waitingBacklogs`).\n */\n async findFreeLanes(\n request: ClaimRequest,\n { laneCount, passed }: { readonly laneCount: number; readonly passed: readonly number[] },\n ): Promise<number[]> {\n const lanes = await this.#state.lanes\n .aggregate<{ _id: number }>([\n {\n $match: {\n _id: { $nin: passed },\n $or: [{ leaseExpiresAt: null }, { leaseExpiresAt: { $lte: request.now } }],\n },\n },\n {\n $lookup: {\n from: this.#state.deliveries.collectionName,\n localField: '_id',\n foreignField: 'laneId',\n pipeline: [\n {\n $match: {\n handler: { $in: [...request.handlers] },\n lane: 'ready',\n dueAt: { $lte: request.now },\n },\n },\n { $sort: { dueAt: 1, _id: 1 } },\n { $limit: 1 },\n { $project: { dueAt: 1 } },\n ],\n as: 'oldest',\n },\n },\n { $unwind: '$oldest' },\n { $sort: { 'oldest.dueAt': 1, 'oldest._id': 1 } },\n { $limit: laneCount },\n { $project: { _id: 1 } },\n ])\n .toArray();\n return lanes.map((lane) => lane._id);\n }\n\n /**\n * Takes the lanes with one conditional write each, run in parallel; a lane\n * taken by someone else meanwhile is skipped. The same write moves the\n * previous owner's in-flight list to `lost`, which is charged before any\n * delivery of the lanes is read (see {@link MongoLaneLeases.chargeLost}).\n */\n async takeLanes(laneIds: readonly number[], request: ClaimRequest): Promise<ScopeLane[]> {\n const after = await Promise.all(\n laneIds.map((laneId) =>\n this.#state.lanes.findOneAndUpdate(\n {\n _id: laneId,\n $or: [{ leaseExpiresAt: null }, { leaseExpiresAt: { $lte: request.now } }],\n },\n [\n {\n $set: {\n epoch: { $add: ['$epoch', 1] },\n owner: { $literal: request.leaseOwner },\n holder: { $literal: this.#state.instanceId },\n leaseExpiresAt: { $literal: request.leaseExpiresAt },\n // Each lost delivery keeps the epoch it was claimed under: the key of its charge.\n lost: {\n $setUnion: [\n { $ifNull: ['$lost', []] },\n { $map: { input: '$inFlight', in: { id: '$$this', epoch: '$epoch' } } },\n ],\n },\n inFlight: { $literal: [] },\n },\n },\n ],\n { returnDocument: 'after' },\n ),\n ),\n );\n const taken = after.filter((lane) => lane !== null);\n await this.chargeLost(taken);\n return taken.map((lane) => ({\n laneId: lane._id,\n epoch: lane.epoch,\n listed: lane.inFlight,\n revision: lane.revision ?? 0,\n }));\n }\n\n /**\n * Charges one attempt to every pending delivery listed in the `lost` lists of\n * `lanes` (deliveries whose lane was taken while they ran), then clears those\n * lists under the lanes' current epochs. The charge is a write on each lost\n * delivery that comes before any read of the lane's deliveries: a completion\n * of the previous owner deletes the same documents, so the two conflict and\n * cannot both succeed. The charge also moves the claim generation on, which\n * fences every lease of the lost claim, and records the lost claim\n * (`lostAt` = lane and epoch it was claimed under): a holder that charges the\n * list again after a failure before the clear skips deliveries already\n * charged for that claim.\n */\n async chargeLost(lanes: readonly LaneDocument[]): Promise<void> {\n const losing = lanes.filter((lane) => lane.lost.length > 0);\n if (losing.length === 0) {\n return;\n }\n // Oldest lost claims first: a delivery's lane never changes and its epochs only grow, so\n // `lostAt` (the epoch of the last lost claim charged) only moves forward, and a charge of a\n // claim at or before it, repeated or delayed, matches nothing.\n const lost = losing\n .flatMap((lane) => lane.lost)\n .sort((left, right) => left.epoch - right.epoch);\n await this.#state.deliveries.bulkWrite(\n lost.map(({ id, epoch }) => ({\n updateOne: {\n filter: { _id: id, status: 'pending', lostAt: { $not: { $gte: epoch } } },\n update: { $inc: { attempts: 1, claims: 1 }, $set: { lostAt: epoch } },\n },\n })),\n { ordered: true },\n );\n await this.#state.lanes.bulkWrite(\n losing.map((lane) => ({\n updateOne: { filter: { _id: lane._id, epoch: lane.epoch }, update: { $set: { lost: [] } } },\n })),\n { ordered: false },\n );\n }\n\n /**\n * Records the picks in their lanes, one conditional write per lane and one\n * round trip for all of them, and frees the lanes that yielded nothing and run\n * nothing. A picked lane lists its running deliveries plus the new ones (ids\n * whose documents are gone are pruned) and its lease reaches\n * `request.leaseExpiresAt`. Returns the lanes whose picks were recorded: every\n * write is conditional on the claim's epoch, owner and store instance, so a\n * lane that changed hands, or was handed back by `relinquish`, in the meantime\n * keeps its deliveries for whoever takes it next.\n */\n async recordClaim(\n scope: ReadonlyMap<number, ScopeLane>,\n {\n picked,\n runningIds,\n request,\n }: {\n readonly picked: readonly DeliveryDocument[];\n readonly runningIds: ReadonlySet<string>;\n readonly request: ClaimRequest;\n },\n ): Promise<{ readonly recorded: Set<number>; readonly handedBack: Set<number> }> {\n const picksByLane = new Map<number, string[]>();\n const handedBack = new Set<number>();\n for (const document of picked) {\n picksByLane.set(document.laneId, [...(picksByLane.get(document.laneId) ?? []), document._id]);\n }\n const operations: Array<AnyBulkWriteOperation<LaneDocument>> = [];\n for (const lane of scope.values()) {\n const gone = lane.listed.filter((id) => !runningIds.has(id));\n const ids = picksByLane.get(lane.laneId);\n if (ids !== undefined) {\n operations.push(\n recordInFlight({ lane, ids, gone, request, instanceId: this.#state.instanceId }),\n );\n } else if (gone.length === lane.listed.length) {\n operations.push(\n freeLane(lane.laneId, { epoch: lane.epoch, revision: lane.revision, finished: gone }),\n );\n handedBack.add(lane.laneId);\n }\n }\n if (operations.length === 0) {\n return { recorded: new Set(), handedBack };\n }\n const result = await this.#state.lanes.bulkWrite(operations, { ordered: false });\n if (result.matchedCount === operations.length) {\n return { recorded: new Set(picksByLane.keys()), handedBack };\n }\n return {\n recorded: await this.#readRecorded(scope, { laneIds: [...picksByLane.keys()], request }),\n handedBack,\n };\n }\n\n /** The lanes of `laneIds` whose record of this claim applied, read back after a partial bulk write. */\n async #readRecorded(\n scope: ReadonlyMap<number, ScopeLane>,\n { laneIds, request }: { readonly laneIds: readonly number[]; readonly request: ClaimRequest },\n ): Promise<Set<number>> {\n const current = await this.#state.lanes\n .find(\n { _id: { $in: [...laneIds] } },\n { projection: { epoch: 1, owner: 1, holder: 1, revision: 1 } },\n )\n .toArray();\n return new Set(\n current\n .filter(\n (lane) =>\n lane.epoch === scope.get(lane._id)!.epoch &&\n lane.revision === scope.get(lane._id)!.revision + 1 &&\n lane.owner === request.leaseOwner &&\n lane.holder === this.#state.instanceId,\n )\n .map((lane) => lane._id),\n );\n }\n\n /** Implements {@link MongoEventStore.relinquish}. */\n async relinquish(leaseOwner: string): Promise<void> {\n const held = await this.#state.lanes\n .find({ owner: String(leaseOwner), holder: this.#state.instanceId })\n .toArray();\n const runningIds = new Set(\n (await this.#queries.findRunning(held.flatMap((lane) => lane.inFlight))).map(\n (document) => document._id,\n ),\n );\n const idle = held.filter((lane) => lane.inFlight.every((id) => !runningIds.has(id)));\n if (idle.length > 0) {\n await this.#state.lanes.bulkWrite(\n idle.map((lane) =>\n freeLane(lane._id, {\n epoch: lane.epoch,\n revision: lane.revision ?? 0,\n finished: lane.inFlight,\n }),\n ),\n { ordered: false },\n );\n }\n }\n}\n\n/** One lane's record of a claim: the picks join its in-flight list and the deliveries no longer running leave it. */\ntype RecordInFlightInput = {\n readonly lane: ScopeLane;\n readonly ids: readonly string[];\n readonly gone: readonly string[];\n readonly request: ClaimRequest;\n readonly instanceId: string;\n};\n\nfunction recordInFlight(input: RecordInFlightInput): AnyBulkWriteOperation<LaneDocument> {\n const { lane, ids, gone, request, instanceId } = input;\n return {\n updateOne: {\n filter: {\n _id: lane.laneId,\n epoch: lane.epoch,\n owner: request.leaseOwner,\n holder: instanceId,\n // A record that reaches the server late (after its claim failed and reconciled)\n // finds a newer revision and changes nothing.\n revision: atCount(lane.revision),\n },\n update: [\n {\n $set: {\n inFlight: {\n $concatArrays: [\n {\n $filter: {\n input: '$inFlight',\n cond: { $not: [{ $in: ['$$this', { $literal: gone }] }] },\n },\n },\n { $literal: ids },\n ],\n },\n leaseExpiresAt: { $max: ['$leaseExpiresAt', request.leaseExpiresAt] },\n revision: { $add: [{ $ifNull: ['$revision', 0] }, 1] },\n },\n },\n ],\n },\n };\n}\n\n/**\n * Frees a lane, provided it still has `epoch` and lists nothing beyond\n * `finished` (ids of deliveries known not to run): a delivery recorded\n * meanwhile keeps the lane leased.\n */\nfunction freeLane(\n laneId: number,\n {\n epoch,\n revision,\n finished,\n }: { readonly epoch: number; readonly revision: number; readonly finished: readonly string[] },\n): AnyBulkWriteOperation<LaneDocument> {\n return {\n updateOne: {\n filter: {\n _id: laneId,\n epoch,\n revision: atCount(revision),\n inFlight: { $not: { $elemMatch: { $nin: [...finished] } } },\n },\n update: {\n $set: { owner: null, holder: null, leaseExpiresAt: null, inFlight: [] },\n $inc: { revision: 1 },\n },\n },\n };\n}\n","import type { ClaimRequest } from '@relaybus/core';\nimport type { Filter } from 'mongodb';\nimport { type ClaimScan, orderingIdentity } from './claim-scan.js';\nimport type { DeliveryDocument } from './documents.js';\nimport type { MongoStoreState, ScopeLane } from './mongo-store-state.js';\n\nconst MINIMUM_CANDIDATE_BATCH_SIZE = 32;\n\nconst PARK_UPDATE_CHUNK_SIZE = 1_000;\n\n/** One round of candidate picking over some lanes of a claim. */\ntype PickCandidatesInput = {\n readonly lanes: readonly ScopeLane[];\n readonly request: ClaimRequest;\n readonly scan: ClaimScan;\n readonly running: Promise<{ readonly keys: Set<string> }>;\n /** The claim's picks so far; this round appends to it. */\n readonly picked: DeliveryDocument[];\n};\n\n/** Picks claimable candidates in key order and parks deliveries stuck behind an unfinished predecessor. */\nexport class MongoOrdering {\n readonly #state: MongoStoreState;\n\n constructor(state: MongoStoreState) {\n this.#state = state;\n }\n\n /**\n * Adds the claimable candidates of `lanes` to `picked`, in due order, until\n * `request.limit` is reached. A delivery is a candidate when it is ready, due\n * and not in flight in its lane. A keyed candidate is claimable only when\n * (a) no earlier delivery of its handler and key is pending (a running one is\n * still a pending document) and (b) no other delivery of them runs. Running\n * deliveries of a key live in the key's lane, which this owner holds, so the\n * running keys (loaded once from the held lanes) and this claim's own picks\n * are all of them.\n *\n * Candidates are read in pages with a limit, so no cursor is left open, and\n * the predecessors of the keys of a page are looked up in parallel, one\n * lookup per key.\n */\n async pickCandidates(input: PickCandidatesInput): Promise<void> {\n const { lanes, request, scan, running, picked } = input;\n const pageSize = Math.max((request.limit - picked.length) * 2, MINIMUM_CANDIDATE_BATCH_SIZE);\n const filter: Filter<DeliveryDocument> = {\n laneId: { $in: lanes.map((lane) => lane.laneId) },\n handler: { $in: [...request.handlers] },\n lane: 'ready',\n dueAt: { $lte: request.now },\n _id: { $nin: lanes.flatMap((lane) => lane.listed) },\n };\n let after: DeliveryDocument | undefined;\n for (;;) {\n const [page, { keys }] = await Promise.all([\n this.#state.deliveries\n .find(\n after === undefined\n ? filter\n : {\n $and: [\n filter,\n {\n $or: [\n { dueAt: { $gt: after.dueAt! } },\n { dueAt: after.dueAt!, _id: { $gt: after._id } },\n ],\n },\n ],\n },\n { sort: { dueAt: 1, _id: 1 }, limit: pageSize },\n )\n .toArray(),\n running,\n ]);\n if (await this.#pickFromPage(page, { request, scan, picked, keys })) {\n return;\n }\n if (page.length < pageSize) {\n return;\n }\n after = page.at(-1);\n }\n }\n\n /**\n * Adds the claimable candidates of `page` to `picked`. Looks up predecessors only for as many\n * candidates as the claim still needs, then more. True once the claim has `request.limit` picks.\n */\n async #pickFromPage(\n page: readonly DeliveryDocument[],\n claim: {\n readonly request: ClaimRequest;\n readonly scan: ClaimScan;\n readonly picked: DeliveryDocument[];\n readonly keys: Set<string>;\n },\n ): Promise<boolean> {\n const { request, scan, picked, keys } = claim;\n for (let offset = 0; offset < page.length;) {\n const slice = page.slice(offset, offset + request.limit - picked.length);\n offset += slice.length;\n await this.#notePredecessors(slice, scan);\n for (const candidate of slice) {\n if (isClaimable(candidate, { scan, blockedKeys: keys })) {\n picked.push(candidate);\n }\n }\n if (picked.length >= request.limit) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Looks up, in parallel and once per key, whether an unfinished delivery\n * precedes the earliest candidate of each keyed (handler, key) of `page` that\n * this claim knows nothing about yet, and tells `scan`. The earliest candidate\n * is itself unfinished, so every later candidate of its key waits at least for it.\n */\n async #notePredecessors(page: readonly DeliveryDocument[], scan: ClaimScan): Promise<void> {\n const earliest = new Map<string, DeliveryDocument>();\n for (const candidate of page) {\n if (candidate.key !== undefined) {\n const orderingId = orderingIdentity(candidate.handler, candidate.key);\n // Pages come in due order, not in sequence order, so keep the lowest sequence.\n const known = earliest.get(orderingId);\n if (!scan.knows(orderingId) && (known?.sequence ?? Infinity) > candidate.sequence!) {\n earliest.set(orderingId, candidate);\n }\n }\n }\n await Promise.all(\n [...earliest].map(async ([orderingId, candidate]) => {\n const predecessor = await this.#findUnfinishedPredecessor(candidate.handler, {\n key: candidate.key!,\n sequence: candidate.sequence!,\n });\n scan.noteOpen(orderingId, predecessor ?? candidate.sequence!);\n }),\n );\n }\n\n /**\n * Parks the waiting backlogs a claim found. Best effort: parking only saves\n * later claims work, so a failure is logged and the claim still returns its\n * batch; the next claim that meets the backlog parks it.\n */\n async parkWaiting(deliveryIds: readonly string[]): Promise<void> {\n try {\n await this.#parkDeliveries(deliveryIds);\n } catch (error) {\n this.#state.logger.warn(\n `[MongoOrdering](parkWaiting) Parking waiting deliveries failed, a later claim parks them | count=${deliveryIds.length} | error=${String(error)}`,\n );\n }\n }\n\n /** Sequence of the lowest unfinished delivery of the handler and key before `sequence`, if any. */\n async #findUnfinishedPredecessor(\n handler: string,\n { key, sequence }: { readonly key: string; readonly sequence: number },\n ): Promise<number | undefined> {\n const predecessor = await this.#state.deliveries.findOne(\n { handler, key, sequence: { $lt: sequence }, dueAt: { $exists: true } },\n { sort: { sequence: 1 }, projection: { sequence: 1 } },\n );\n return predecessor?.sequence;\n }\n\n /**\n * Parks pending deliveries that waited behind an unfinished predecessor, which\n * removes them from the claim index until their turn. Parking is a hint, not a\n * guarantee: a predecessor that finishes meanwhile is found by the next\n * {@link MongoEventStore.claim}, which moves the lowest parked delivery back.\n */\n async #parkDeliveries(deliveryIds: readonly string[]): Promise<void> {\n for (let offset = 0; offset < deliveryIds.length; offset += PARK_UPDATE_CHUNK_SIZE) {\n await this.#state.deliveries.updateMany(\n {\n _id: { $in: deliveryIds.slice(offset, offset + PARK_UPDATE_CHUNK_SIZE) },\n status: 'pending',\n lane: 'ready',\n },\n { $set: { lane: 'parked' } },\n );\n }\n }\n\n /**\n * Moves the lowest parked delivery of every parked key of `handlers` back into\n * the claim index when nothing unfinished precedes it. Level-triggered on\n * purpose: it looks at the current state only, so a crash anywhere, or a\n * predecessor finishing while its followers were being parked, can delay a key\n * until the next claim but never strand it.\n */\n async unparkNextDeliveries(handlers: readonly string[]): Promise<void> {\n const anyParked = await this.#state.deliveries.findOne(\n { handler: { $in: [...handlers] }, lane: 'parked' },\n // The sort lets the planner pick the small partial index over the handler's whole history.\n { sort: { handler: 1, key: 1, sequence: 1 }, projection: { _id: 1 } },\n );\n if (anyParked === null) {\n return;\n }\n // The lowest parked delivery of every key, one aggregation per handler in parallel. With the\n // handler fixed and one group field, the server answers it with a distinct scan of the small\n // partial index: one index probe per parked key, not one per parked delivery.\n const lowest = (\n await Promise.all(\n [...new Set(handlers)].map((handler) =>\n this.#state.deliveries\n .aggregate<{ _id: string; id: string; sequence: number }>([\n { $match: { handler, lane: 'parked' } },\n { $sort: { handler: 1, key: 1, sequence: 1 } },\n {\n $group: { _id: '$key', id: { $first: '$_id' }, sequence: { $first: '$sequence' } },\n },\n ])\n .toArray()\n .then((groups) => groups.map((group) => ({ ...group, handler }))),\n ),\n )\n ).flat();\n const next = await Promise.all(\n lowest.map(async (parked) =>\n (await this.#findUnfinishedPredecessor(parked.handler, {\n key: parked._id,\n sequence: parked.sequence,\n })) === undefined\n ? [parked.id]\n : [],\n ),\n );\n const ready = next.flat();\n if (ready.length > 0) {\n await this.#state.deliveries.updateMany(\n { _id: { $in: ready }, lane: 'parked' },\n { $set: { lane: 'ready' } },\n );\n }\n }\n}\n\n/**\n * Whether a candidate may be claimed, given what `scan` knows about its key\n * (see `MongoOrdering.#notePredecessors`) and `blockedKeys`: the keys that\n * run, to which every key this claim takes is added, so a claim takes at most\n * one delivery per key.\n */\nfunction isClaimable(\n candidate: DeliveryDocument,\n { scan, blockedKeys }: { readonly scan: ClaimScan; readonly blockedKeys: Set<string> },\n): boolean {\n const { key, sequence } = candidate;\n if (key === undefined) {\n return true;\n }\n const orderingId = orderingIdentity(candidate.handler, key);\n if (scan.waits(orderingId, sequence!)) {\n scan.noteWaiting(orderingId, { deliveryId: candidate._id, laneId: candidate.laneId });\n return false;\n }\n if (blockedKeys.has(orderingId)) {\n return false;\n }\n blockedKeys.add(orderingId);\n return true;\n}\n","import type { PurgeRequest, PurgeResult } from '@relaybus/core';\nimport type { ClientSession, Collection, Filter } from 'mongodb';\nimport { runInTransaction, type MongoStoreState } from './mongo-store-state.js';\n\n/** The fields purge reads from a delivery or a completion history record. */\ninterface PurgeableDocument {\n readonly _id: string;\n readonly eventId: string;\n readonly status?: string;\n readonly completedAt?: Date;\n readonly updatedAt?: Date;\n}\n\n/** Deletes old completed and dead deliveries and the events nothing references any more. */\nexport class MongoPurge {\n readonly #state: MongoStoreState;\n\n constructor(state: MongoStoreState) {\n this.#state = state;\n }\n\n /** Implements {@link MongoEventStore.purge}. */\n async purge(request: PurgeRequest): Promise<PurgeResult> {\n const total = { deletedDeliveries: 0, deletedEvents: 0 };\n const steps: Array<() => Promise<PurgeResult>> = [];\n const { completedBefore, deadBefore } = request;\n if (completedBefore !== undefined) {\n steps.push(() =>\n this.#purgeMatching(this.#purgeable(this.#state.deliveries.collectionName), {\n filter: { status: 'completed', completedAt: { $lt: completedBefore } },\n completedBefore,\n }),\n );\n if (this.#state.completionHistory) {\n steps.push(() =>\n this.#purgeMatching(this.#purgeable(this.#state.completions.collectionName), {\n filter: { completedAt: { $lt: completedBefore } },\n completedBefore,\n }),\n );\n }\n }\n if (deadBefore !== undefined) {\n steps.push(() =>\n this.#purgeMatching(this.#purgeable(this.#state.deliveries.collectionName), {\n filter: { status: 'dead', updatedAt: { $lt: deadBefore } },\n completedBefore,\n }),\n );\n }\n for (const step of steps) {\n const result = await step();\n total.deletedDeliveries += result.deletedDeliveries;\n total.deletedEvents += result.deletedEvents;\n }\n const orphanCutoff = [completedBefore, deadBefore]\n .filter((cutoff) => cutoff !== undefined)\n .sort((first, second) => first.getTime() - second.getTime())[0];\n if (orphanCutoff !== undefined) {\n total.deletedEvents += await this.#purgeOrphanEvents(orphanCutoff, completedBefore);\n }\n return total;\n }\n\n /**\n * Deletes batches of matching documents (deliveries, or completion history\n * records) together with the events nothing references any more, each batch\n * in one transaction, so a crash can never leave an event without deliveries\n * behind. An append adding a delivery to the same event writes the event\n * document, so the two conflict and one restarts instead of leaving a delivery\n * without event. A delivery requeued since the batch was read conflicts with\n * its deletion and is read again.\n */\n async #purgeMatching(\n collection: Collection<PurgeableDocument>,\n {\n filter,\n completedBefore,\n }: { readonly filter: Filter<PurgeableDocument>; readonly completedBefore: Date | undefined },\n ): Promise<PurgeResult> {\n let deletedDeliveries = 0;\n let deletedEvents = 0;\n for (;;) {\n const step = await runInTransaction(this.#state, async (session) => {\n const batch = await collection\n .find(filter, { session, projection: { eventId: 1 }, limit: this.#state.purgeBatchSize })\n .toArray();\n if (batch.length === 0) {\n return { batchSize: 0, deletedDeliveries: 0, deletedEvents: 0 };\n }\n const eventIds = [...new Set(batch.map((document) => document.eventId))];\n const deleted = await collection.deleteMany(\n { _id: { $in: batch.map((document) => document._id) } },\n { session },\n );\n const stillReferenced = await this.#referencedEventIds(eventIds, session);\n const events = await this.#state.events.deleteMany(\n {\n _id: { $in: eventIds.filter((eventId) => !stillReferenced.has(eventId)) },\n // An event a delivery of which completed stays as deduplication record until\n // `completedBefore` passes its last completion, whatever this batch purged.\n $or: [\n { completedAt: { $exists: false } },\n ...(completedBefore === undefined ? [] : [{ completedAt: { $lt: completedBefore } }]),\n ],\n },\n { session },\n );\n return {\n batchSize: batch.length,\n deletedDeliveries: deleted.deletedCount,\n deletedEvents: events.deletedCount,\n };\n });\n deletedDeliveries += step.deletedDeliveries;\n deletedEvents += step.deletedEvents;\n if (step.batchSize < this.#state.purgeBatchSize) {\n return { deletedDeliveries, deletedEvents };\n }\n }\n }\n\n /** A view of a collection that purge deletes from: deliveries or completion history records. */\n #purgeable(name: string): Collection<PurgeableDocument> {\n return this.#state.database.collection<PurgeableDocument>(name, {\n readPreference: 'primary',\n writeConcern: { w: 'majority' },\n });\n }\n\n /** Those of `eventIds` that a delivery or a completion history record references. */\n async #referencedEventIds(\n eventIds: readonly string[],\n session: ClientSession,\n ): Promise<Set<string>> {\n const filter = { eventId: { $in: [...eventIds] } };\n const options = { session, projection: { eventId: 1 } };\n const references = [\n ...(await this.#state.deliveries.find(filter, options).toArray()),\n ...(this.#state.completionHistory\n ? await this.#state.completions.find(filter, options).toArray()\n : []),\n ];\n return new Set(references.map((reference) => reference.eventId));\n }\n\n /**\n * Deletes, in batches, events created before `cutoff` that no delivery (or\n * completion history record) references. Each batch is found and deleted in\n * one transaction: an append adding a delivery to one of them writes the\n * event, so it conflicts with the deletion, which then restarts and sees the\n * delivery. Returns how many events were deleted.\n */\n async #purgeOrphanEvents(cutoff: Date, completedBefore: Date | undefined): Promise<number> {\n const references = [\n this.#state.deliveries.collectionName,\n ...(this.#state.completionHistory ? [this.#state.completions.collectionName] : []),\n ];\n let deletedEvents = 0;\n for (;;) {\n const step = await runInTransaction(this.#state, async (session) => {\n const orphans = await this.#state.events\n .aggregate<{ _id: string }>(\n [\n {\n $match: {\n $or: [\n // Never completed (no subscribers, or every delivery dead): by age.\n { completedAt: { $exists: false }, createdAt: { $lt: cutoff } },\n // Completed: by the time of its last completion, and only under the completed cutoff.\n ...(completedBefore === undefined\n ? []\n : [{ completedAt: { $lt: completedBefore } }]),\n ],\n },\n },\n { $sort: { createdAt: 1, _id: 1 } },\n ...references.flatMap((from) => [\n {\n $lookup: {\n from,\n localField: '_id',\n foreignField: 'eventId',\n pipeline: [{ $limit: 1 }, { $project: { _id: 1 } }],\n as: 'references',\n },\n },\n { $match: { references: { $size: 0 } } },\n ]),\n { $limit: this.#state.purgeBatchSize },\n { $project: { _id: 1 } },\n ],\n { session },\n )\n .toArray();\n const deleted = await this.#state.events.deleteMany(\n { _id: { $in: orphans.map((orphan) => orphan._id) } },\n { session },\n );\n return { found: orphans.length, deleted: deleted.deletedCount };\n });\n deletedEvents += step.deleted;\n if (step.found < this.#state.purgeBatchSize) {\n return deletedEvents;\n }\n }\n }\n}\n","import {\n type DeliveryQuery,\n type DeliveryRecord,\n type EventEnvelope,\n type EventStoreStatistics,\n} from '@relaybus/core';\nimport type { Filter } from 'mongodb';\nimport {\n toCompletedDeliveryRecord,\n toDeliveryRecord,\n toEnvelope,\n type DeliveryDocument,\n} from './documents.js';\nimport type { MongoStoreState } from './mongo-store-state.js';\n\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Reads for listing, requeueing and statistics, and the lookups the claim shares. */\nexport class MongoQueries {\n readonly #state: MongoStoreState;\n\n constructor(state: MongoStoreState) {\n this.#state = state;\n }\n\n /** Implements {@link MongoEventStore.listDeliveries}. */\n async listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]> {\n // Strings only: an object here (say, parsed from an admin request) would be a query operator.\n const status = query.status === undefined ? undefined : String(query.status);\n const common = commonFilter(query);\n const limit = query.limit ?? DEFAULT_LIST_LIMIT;\n const lanes = await this.#state.lanes\n .find({ 'inFlight.0': { $exists: true } }, { projection: { epoch: 0 } })\n .toArray();\n const listed = lanes.flatMap((lane) => lane.inFlight);\n // A Map, not an object: an untrusted status such as 'constructor' must not find anything.\n const derivedStatuses = new Map<string, Filter<DeliveryDocument>>([\n ['processing', { status: 'pending', _id: { $in: listed } }],\n ['pending', { status: 'pending', _id: { $nin: listed } }],\n ]);\n const filter: Filter<DeliveryDocument> = {\n ...common,\n ...(status === undefined\n ? {}\n : (derivedStatuses.get(status) ?? { status: status as DeliveryDocument['status'] })),\n };\n const sort = { createdAt: 1, _id: 1 } as const;\n const documents = await this.#state.deliveries.find(filter, { sort, limit }).toArray();\n const history =\n this.#state.completionHistory && (status === undefined || status === 'completed')\n ? await this.#state.completions.find(common, { sort, limit }).toArray()\n : [];\n const events = await this.readEnvelopes([\n ...documents.map((document) => document.eventId),\n ...history.map((document) => document.eventId),\n ]);\n const laneById = new Map(lanes.map((lane) => [lane._id, lane]));\n const records = [\n ...documents.map((document) => {\n const lane = laneById.get(document.laneId);\n const runs =\n document.status === 'pending' && lane?.inFlight.includes(document._id) === true;\n return toDeliveryRecord(document, {\n event: events.get(document.eventId)!,\n runningIn: runs ? lane : undefined,\n });\n }),\n ...history.map((document) =>\n toCompletedDeliveryRecord(document, events.get(document.eventId)!),\n ),\n ];\n return records\n .sort(\n (left, right) =>\n left.createdAt.getTime() - right.createdAt.getTime() || compareText(left.id, right.id),\n )\n .slice(0, limit);\n }\n\n /** Implements {@link MongoEventStore.requeue}. */\n async requeue(deliveryIds: readonly string[], now: Date): Promise<number> {\n const result = await this.#state.deliveries.updateMany(\n { _id: { $in: deliveryIds.map(String) }, status: 'dead' },\n {\n $set: {\n status: 'pending',\n lane: 'ready',\n attempts: 0,\n availableAt: now,\n dueAt: now,\n updatedAt: now,\n },\n },\n );\n return result.modifiedCount;\n }\n\n /** Implements {@link MongoEventStore.statistics}. */\n async statistics(now: Date): Promise<EventStoreStatistics> {\n const lanes = await this.#state.lanes\n .find({ 'inFlight.0': { $exists: true } }, { projection: { inFlight: 1, leaseExpiresAt: 1 } })\n .toArray();\n // Index-only counts in parallel: measured at 300k deliveries they take 27 ms, against\n // 121 ms for one $group, which has to read every document or index entry.\n const [stored, dead, legacyCompleted, history, running] = await Promise.all([\n this.#state.deliveries.countDocuments({ status: 'pending' }),\n this.#state.deliveries.countDocuments({ status: 'dead' }),\n this.#state.deliveries.countDocuments({ status: 'completed' }),\n this.#state.completionHistory ? this.#state.completions.countDocuments() : Promise.resolve(0),\n this.findRunning(lanes.flatMap((lane) => lane.inFlight)),\n ]);\n const runningIds = new Set(running.map((document) => document._id));\n const waiting = await this.#state.deliveries.findOne(\n { dueAt: { $lte: now }, _id: { $nin: [...runningIds] } },\n { sort: { dueAt: 1 }, projection: { dueAt: 1 } },\n );\n const dueTimes = lanes\n .filter(\n (lane) =>\n lane.leaseExpiresAt !== null &&\n lane.leaseExpiresAt <= now &&\n lane.inFlight.some((id) => runningIds.has(id)),\n )\n .map((lane) => lane.leaseExpiresAt!.getTime());\n if (waiting !== null) {\n dueTimes.push(waiting.dueAt!.getTime());\n }\n return {\n // The counts are separate reads; a completion between them must not make this negative.\n pending: Math.max(0, stored - running.length),\n processing: running.length,\n completed: legacyCompleted + history,\n dead,\n oldestDueAt: dueTimes.length === 0 ? null : new Date(Math.min(...dueTimes)),\n };\n }\n\n /** The listed deliveries that run: those whose document still exists as pending. */\n async findRunning(listed: readonly string[]): Promise<DeliveryDocument[]> {\n if (listed.length === 0) {\n return [];\n }\n return this.#state.deliveries\n .find(\n { _id: { $in: [...listed] }, status: 'pending' },\n { projection: { handler: 1, key: 1, laneId: 1 } },\n )\n .toArray();\n }\n\n async readEnvelopes(eventIds: readonly string[]): Promise<Map<string, EventEnvelope>> {\n const documents = await this.#state.events\n .find({ _id: { $in: [...new Set(eventIds)] } })\n .toArray();\n return new Map(documents.map((document) => [document._id, toEnvelope(document)]));\n }\n}\n\nfunction compareText(left: string, right: string): number {\n return Number(left > right) - Number(left < right);\n}\n\n/** The filters every listed collection shares, as strings: an object would be a query operator. */\nfunction commonFilter(query: DeliveryQuery): {\n handler?: string;\n eventType?: string;\n eventId?: string;\n} {\n return {\n ...(query.handler === undefined ? {} : { handler: String(query.handler) }),\n ...(query.eventType === undefined ? {} : { eventType: String(query.eventType) }),\n ...(query.eventId === undefined ? {} : { eventId: String(query.eventId) }),\n };\n}\n","import type { Document, IndexDescriptionInfo } from 'mongodb';\nimport { LANE_COUNT, laneOf } from './lanes.js';\nimport { createTransactionsUnsupportedError } from './mongo-errors.js';\nimport type { MongoStoreState } from './mongo-store-state.js';\n\nconst NAMESPACE_EXISTS = 48;\n\nconst INDEX_NOT_FOUND = 27;\n\n/** Documents converted per write while `setup()` upgrades a 0.1.0 database. */\nconst UPGRADE_BATCH_SIZE = 1_000;\n\n/** Key of the claim index. A 0.1.0 index named `claim` with another key is dropped by `setup()`. */\nconst CLAIM_INDEX_KEY = { laneId: 1, dueAt: 1, _id: 1, handler: 1 } as const;\n\n/** Indexes of 0.1.0 that no query uses any more. */\nconst OBSOLETE_INDEXES = ['running'];\n\n/** Fields that 0.1.0 stored while a delivery was leased. */\nconst LEASE_FIELDS = { leaseOwner: '', leaseToken: '', leaseExpiresAt: '' } as const;\n\n/** Creates the collections and indexes, seeds the lanes and upgrades a 0.1.0 database. */\nexport class MongoSchema {\n readonly #state: MongoStoreState;\n\n constructor(state: MongoStoreState) {\n this.#state = state;\n }\n\n /** Implements {@link MongoEventStore.setup}. */\n async setup(): Promise<void> {\n const hello = await this.#state.client.db('admin').command({ hello: 1 });\n const supportsTransactions =\n typeof hello['setName'] === 'string' || hello['msg'] === 'isdbgrid';\n if (!supportsTransactions) {\n throw createTransactionsUnsupportedError(undefined);\n }\n // Created up front: collections created implicitly inside concurrent transactions conflict.\n const collectionNames = [\n this.#state.events.collectionName,\n this.#state.deliveries.collectionName,\n this.#state.keySequences.collectionName,\n this.#state.lanes.collectionName,\n ...(this.#state.completionHistory ? [this.#state.completions.collectionName] : []),\n ];\n for (const name of collectionNames) {\n await this.#createCollectionIfMissing(name);\n }\n if ((await this.#state.lanes.countDocuments()) < LANE_COUNT) {\n await this.#upgradeFromVersion010();\n await this.#seedLanes();\n }\n await this.#dropObsoleteIndexes();\n await this.#createIndexes();\n }\n\n /** Creates the indexes of every collection; existing indexes are left as they are. */\n async #createIndexes(): Promise<void> {\n await this.#state.deliveries.createIndexes([\n // Idempotent appends and lookups by event.\n { key: { eventId: 1, handler: 1 }, name: 'event_handler', unique: true },\n // Claim: due work of a lane in due order. Holds ready deliveries only. The handler is\n // last, so a query over many lanes and handlers stays a merge of one scan per lane.\n { key: CLAIM_INDEX_KEY, name: 'claim', partialFilterExpression: { lane: 'ready' } },\n // Ordering: unfinished predecessors of a keyed delivery, parked or not.\n {\n key: { handler: 1, key: 1, sequence: 1 },\n name: 'ordering',\n partialFilterExpression: { dueAt: { $exists: true }, sequence: { $exists: true } },\n },\n // Parked deliveries: the lowest parked delivery of each key, to move it back once it is next.\n {\n key: { handler: 1, key: 1, sequence: 1 },\n name: 'parked',\n partialFilterExpression: { lane: 'parked' },\n },\n // Statistics: oldest due delivery across handlers.\n { key: { dueAt: 1 }, name: 'due', partialFilterExpression: { dueAt: { $exists: true } } },\n // Purge of completed deliveries left by 0.1.0.\n {\n key: { completedAt: 1 },\n name: 'completed',\n partialFilterExpression: { completedAt: { $exists: true } },\n },\n // Listing and status counts.\n { key: { status: 1, createdAt: 1 }, name: 'status_created' },\n // Purge of dead deliveries.\n { key: { status: 1, updatedAt: 1 }, name: 'status_updated' },\n { key: { handler: 1, createdAt: 1 }, name: 'handler_created' },\n { key: { eventType: 1, createdAt: 1 }, name: 'type_created' },\n ]);\n // Purge of events no delivery references any more.\n await this.#state.events.createIndexes([\n { key: { createdAt: 1, _id: 1 }, name: 'created' },\n // Purge of events whose deliveries all completed: they are kept until `completedBefore` passes this.\n {\n key: { completedAt: 1, _id: 1 },\n name: 'completed',\n partialFilterExpression: { completedAt: { $exists: true } },\n },\n ]);\n if (this.#state.completionHistory) {\n await this.#state.completions.createIndexes([\n { key: { completedAt: 1, _id: 1 }, name: 'completed' },\n { key: { eventId: 1 }, name: 'event' },\n { key: { createdAt: 1, _id: 1 }, name: 'created' },\n ]);\n }\n }\n\n async #createCollectionIfMissing(name: string): Promise<void> {\n try {\n await this.#state.database.createCollection(name);\n } catch (error) {\n if (!hasErrorCode(error, NAMESPACE_EXISTS)) {\n throw error;\n }\n }\n }\n\n /**\n * Converts the documents of a 0.1.0 database; every step is idempotent, so a\n * run that crashed is simply repeated. Deliveries that were `processing`\n * become `pending`, due at once (their attempt stays counted, as a lost lease\n * would count it). The per-delivery lease fields go, every delivery gets its\n * lane, and every event learns which handlers it already has deliveries for\n * and when it was created. Deliveries completed under 0.1.0 stay as\n * `completed` documents until a purge removes them.\n */\n async #upgradeFromVersion010(): Promise<void> {\n // Untyped view: these documents have the 0.1.0 shape until this method converted them.\n const legacy = this.#state.database.collection(this.#state.deliveries.collectionName);\n await legacy.updateMany({ status: 'processing' }, [\n { $set: { status: 'pending', lane: 'ready', dueAt: '$availableAt' } },\n ]);\n await legacy.updateMany(\n {\n $or: [\n { leaseOwner: { $exists: true } },\n { leaseToken: { $exists: true } },\n { leaseExpiresAt: { $exists: true } },\n ],\n },\n { $unset: LEASE_FIELDS },\n );\n await inBatches(\n this.#state.deliveries.find(\n { laneId: { $exists: false } },\n { projection: { eventId: 1, key: 1 }, batchSize: UPGRADE_BATCH_SIZE },\n ),\n async (documents) => {\n await this.#state.deliveries.bulkWrite(\n documents.map((document) => ({\n updateOne: {\n filter: { _id: document._id },\n update: { $set: { laneId: laneOf(document.key ?? null, document.eventId) } },\n },\n })),\n { ordered: false },\n );\n },\n );\n await this.#upgradeEventsFromVersion010();\n }\n\n /** Tells every 0.1.0 event which handlers it already has deliveries for and when it was created. */\n async #upgradeEventsFromVersion010(): Promise<void> {\n await inBatches(\n this.#state.events.find(\n { handlers: { $exists: false } },\n { projection: { occurredAt: 1 }, batchSize: UPGRADE_BATCH_SIZE },\n ),\n async (events) => {\n const known = new Map(\n (\n await this.#state.deliveries\n .aggregate<{ _id: string; handlers: string[]; createdAt: Date }>([\n { $match: { eventId: { $in: events.map((event) => event._id) } } },\n {\n $group: {\n _id: '$eventId',\n handlers: { $addToSet: '$handler' },\n createdAt: { $min: '$createdAt' },\n },\n },\n ])\n .toArray()\n ).map((group) => [group._id, group]),\n );\n await this.#state.events.bulkWrite(\n events.map((event) => {\n const group = known.get(event._id);\n return {\n updateOne: {\n // Only an event nobody converted yet: another process may have finished and subscribed a handler.\n filter: { _id: event._id, handlers: { $exists: false } },\n update: {\n $set:\n group === undefined\n ? { handlers: [], createdAt: event.occurredAt }\n : { handlers: group.handlers, createdAt: group.createdAt },\n },\n },\n };\n }),\n { ordered: false },\n );\n },\n );\n }\n\n /** Creates the lane documents that do not exist yet. */\n async #seedLanes(): Promise<void> {\n await this.#state.lanes.bulkWrite(\n Array.from({ length: LANE_COUNT }, (_, laneId) => ({\n updateOne: {\n filter: { _id: laneId },\n update: {\n $setOnInsert: {\n epoch: 0,\n owner: null,\n holder: null,\n leaseExpiresAt: null,\n inFlight: [],\n lost: [],\n },\n },\n upsert: true,\n },\n })),\n { ordered: false },\n );\n }\n\n /** Drops the 0.1.0 indexes that no query uses, and a `claim` index with the 0.1.0 key. */\n async #dropObsoleteIndexes(): Promise<void> {\n for (const index of await this.#state.deliveries.indexes()) {\n if (isObsoleteIndex(index)) {\n await this.#dropIndexIfPresent(index.name!);\n }\n }\n }\n\n async #dropIndexIfPresent(name: string): Promise<void> {\n try {\n await this.#state.deliveries.dropIndex(name);\n } catch (error) {\n // Another process running setup() dropped it first.\n if (!hasErrorCode(error, INDEX_NOT_FOUND)) {\n throw error;\n }\n }\n }\n}\n\nfunction isObsoleteIndex(index: IndexDescriptionInfo): boolean {\n return (\n OBSOLETE_INDEXES.includes(index.name!) ||\n (index.name === 'claim' &&\n Object.keys(index.key).join() !== Object.keys(CLAIM_INDEX_KEY).join())\n );\n}\n\n/** Feeds the documents of `cursor` to `work` in batches of the cursor's batch size. */\nasync function inBatches<T extends Document>(\n cursor: AsyncIterable<T>,\n work: (batch: T[]) => Promise<void>,\n): Promise<void> {\n let batch: T[] = [];\n for await (const document of cursor) {\n batch.push(document);\n if (batch.length === UPGRADE_BATCH_SIZE) {\n await work(batch);\n batch = [];\n }\n }\n if (batch.length > 0) {\n await work(batch);\n }\n}\n\nfunction hasErrorCode(error: unknown, code: number): boolean {\n return typeof error === 'object' && error !== null && 'code' in error && error.code === code;\n}\n","import { ConfigurationError } from '@relaybus/core';\n\nconst COLLECTION_PREFIX_PATTERN = /^[A-Za-z_][A-Za-z0-9_]{0,39}$/;\nconst DATABASE_NAME_PATTERN = /^[A-Za-z0-9_-]{1,63}$/;\n\n/** Rejects prefixes that are not safe, portable collection name starts. */\nexport function assertCollectionPrefix(prefix: string): void {\n if (!COLLECTION_PREFIX_PATTERN.test(prefix)) {\n throw new ConfigurationError(\n `collectionPrefix '${prefix}' must be 1-40 characters of letters, digits or '_', starting with a letter or '_'`,\n );\n }\n}\n\n/** Rejects database names MongoDB would refuse or that need escaping. */\nexport function assertDatabaseName(name: string): void {\n if (!DATABASE_NAME_PATTERN.test(name)) {\n throw new ConfigurationError(\n `database '${name}' must be 1-63 characters of letters, digits, '_' or '-'`,\n );\n }\n}\n","import {\n createUuidV7,\n type AppendEntry,\n type AppendResult,\n type ClaimRequest,\n type ClaimedDelivery,\n type DeliveryQuery,\n type DeliveryRecord,\n type ErrorInfo,\n type EventStore,\n type EventStoreStatistics,\n type EventStoreTransactionOptions,\n type IdentifierGenerator,\n type LeaseReference,\n type PurgeRequest,\n type PurgeResult,\n type RelayBusLogger,\n} from '@relaybus/core';\nimport { assertPositiveInteger } from '@relaybus/core/internal';\nimport type { ClientSession, MongoClient, TransactionOptions } from 'mongodb';\nimport { MongoAppend } from './mongo-append.js';\nimport { MongoClaims } from './mongo-claim.js';\nimport { MongoCompletion } from './mongo-completion.js';\nimport { MongoLaneLeases } from './mongo-lane-leases.js';\nimport { MongoOrdering } from './mongo-ordering.js';\nimport { MongoPurge } from './mongo-purge.js';\nimport { MongoQueries } from './mongo-queries.js';\nimport { MongoSchema } from './mongo-schema.js';\nimport {\n runInBudgetedTransaction,\n runInTransaction,\n type MongoStoreState,\n} from './mongo-store-state.js';\nimport { assertCollectionPrefix, assertDatabaseName } from './naming.js';\n\nexport interface MongoEventStoreOptions {\n /** Connected client. The store never closes it. */\n readonly client: MongoClient;\n /** Database holding the relaybus collections. Default: the client's default database. */\n readonly database?: string;\n /** Prefix of the collection names. Default `relaybus_`. */\n readonly collectionPrefix?: string;\n /**\n * Options of the transactions the store opens. Default: snapshot read\n * concern, majority write concern, primary reads.\n */\n readonly transactionOptions?: TransactionOptions;\n /** Rows deleted per purge step. Default 500. */\n readonly purgeBatchSize?: number;\n /**\n * Keep an append-only record of every completed delivery in\n * `<prefix>completed_deliveries`, listed as `completed`, counted by\n * `statistics` and removed by `purge({ completedBefore })`. Default false: a\n * completed delivery is deleted and leaves nothing behind. Use the same value\n * in every process.\n */\n readonly completionHistory?: boolean;\n /** Receives warnings about best-effort steps that failed (parking). Default `console`. */\n readonly logger?: RelayBusLogger;\n /**\n * @deprecated Ignored. Lease tokens name the lane and its epoch\n * (`<laneId>:<epoch>:<claims>`) and are no longer generated.\n */\n readonly generateIdentifier?: IdentifierGenerator;\n}\n\nconst DEFAULT_TRANSACTION_OPTIONS: TransactionOptions = {\n readConcern: { level: 'snapshot' },\n writeConcern: { w: 'majority' },\n readPreference: 'primary',\n};\nconst DEFAULT_PURGE_BATCH_SIZE = 500;\n\n/**\n * Event store on MongoDB 6+ multi-document transactions (replica set or sharded\n * cluster). The transaction handle is the driver's `ClientSession`, so the same\n * session can carry your own writes (native driver or Mongoose).\n *\n * Guarantees:\n * - **Atomic, idempotent append.** `append` is atomic with the caller's writes\n * and idempotent on event id and on (event id, handler). An event remembers\n * every handler it ever had a delivery for, so a redelivered or republished\n * event never runs a completed handler again although completed deliveries are\n * deleted. Duplicates are detected by reading, never by catching a\n * duplicate-key error, which would abort the surrounding transaction.\n * - **Per-key order.** Per-key sequences come from a counter document inside the\n * append transaction. Two transactions appending the same key cannot both hold\n * the counter, so the loser conflicts, restarts after the winner committed, and\n * its sequence is higher: sequence order is commit order. A keyed delivery is\n * claimed only when no earlier delivery of its handler and key is pending and\n * no other delivery of them runs.\n * - **Lane leases.** Every delivery belongs to one of 256 lanes (a hash of its\n * ordering key, or of its event id), so all deliveries of a key share a lane.\n * Workers lease lanes with one conditional write on a lane document, and a\n * claim records its whole batch in the lane documents: it writes no delivery\n * document. While a lane lease is live, other workers do not see the pending\n * deliveries of that lane, even idle ones. A lane changes hands only when its\n * lease expired or its owner handed it back.\n * - **Fencing.** A lease token is `<laneId>:<epoch>:<claims>`. The epoch grows\n * whenever the lane is taken; `claims`, the delivery's claim generation, grows\n * whenever a claim of it ends (retry, release, burial, lost lease), so the\n * lease of an earlier claim never matches a later claim of the same delivery\n * in the same lane epoch. Completion, retry, burial, release and renewal apply\n * only while the lane has that epoch, lists the delivery as in flight, and the\n * delivery has that claim generation.\n * - **Effectively-once for transactional handlers.** A worker that takes a lane\n * over first writes every delivery the previous owner had in flight (it\n * charges the lost attempt) and only then reads what to claim. A completion\n * inside a transaction (a transactional handler's, or any completion when a\n * completion history is kept) deletes the delivery after checking the lane:\n * both write the same delivery document, so the later of the two either\n * conflicts and retries (and then sees the new epoch or the missing\n * delivery), or waits for the earlier to commit. Other completions run\n * without a transaction: they read the deliveries' claim generations, then\n * the lanes, and delete only deliveries whose generation did not change,\n * which a takeover, a retry or a release always changes. Either way a completion and a takeover\n * cannot both succeed. Completions never write the lane document, so\n * concurrent completions of one lane never conflict with each other.\n * - **Attempts survive crashes.** `attempts` counts attempts that ended. The\n * claim result reports `attempts + 1`; a failure records it; a lane taken over\n * charges one attempt to every delivery the previous owner still had in flight,\n * so a poison message still reaches the retry limit after crashes.\n *\n * - **Deduplication record.** A completion records its time on the event\n * (`completedAt`). An event nothing references any more stays until\n * `purge({ completedBefore })` passes that time, however old the event is, and\n * `deadBefore` alone never removes it. Once purged, the event takes its list\n * of handlers with it: a broker redelivery or publish retry of that event id\n * afterwards is appended as a new event and runs its handlers again, as in\n * the PostgreSQL store, so keep completed retention longer than any\n * redelivery window.\n *\n * `transaction` may run `work` more than once (see {@link MongoEventStore.transaction}).\n * Claims of one `leaseOwner` on one store instance run one after the other\n * (a claim that overlaps another of the same owner waits for it); different\n * owners claim concurrently, from any number of processes. Lanes are held per store\n * instance, so a process restarted with the same `leaseOwner` takes its\n * predecessor's lanes over only once their leases expired.\n */\nexport class MongoEventStore implements EventStore<ClientSession> {\n readonly #state: MongoStoreState;\n readonly #schema: MongoSchema;\n readonly #appender: MongoAppend;\n readonly #claims: MongoClaims;\n readonly #laneLeases: MongoLaneLeases;\n readonly #completion: MongoCompletion;\n readonly #queries: MongoQueries;\n readonly #purger: MongoPurge;\n\n constructor(options: MongoEventStoreOptions) {\n const prefix = options.collectionPrefix ?? 'relaybus_';\n assertCollectionPrefix(prefix);\n if (options.database !== undefined) {\n assertDatabaseName(options.database);\n }\n const purgeBatchSize = assertPositiveInteger(\n options.purgeBatchSize ?? DEFAULT_PURGE_BATCH_SIZE,\n 'purgeBatchSize',\n );\n const database = options.client.db(options.database);\n // Majority writes make a lease durable; primary reads keep the ordering check fresh.\n const collectionOptions = {\n readPreference: 'primary',\n writeConcern: { w: 'majority' },\n } as const;\n const state: MongoStoreState = {\n client: options.client,\n database,\n events: database.collection(`${prefix}events`, collectionOptions),\n deliveries: database.collection(`${prefix}deliveries`, collectionOptions),\n keySequences: database.collection(`${prefix}key_sequences`, collectionOptions),\n lanes: database.collection(`${prefix}lanes`, collectionOptions),\n completions: database.collection(`${prefix}completed_deliveries`, collectionOptions),\n completionHistory: options.completionHistory ?? false,\n transactionOptions: options.transactionOptions ?? DEFAULT_TRANSACTION_OPTIONS,\n purgeBatchSize,\n logger: options.logger ?? console,\n instanceId: createUuidV7(),\n claimsInProgress: new Map(),\n handedOut: new Map(),\n unreconciledOwners: new Set(),\n };\n this.#state = state;\n const queries = new MongoQueries(state);\n const ordering = new MongoOrdering(state);\n const laneLeases = new MongoLaneLeases(state, { queries });\n this.#schema = new MongoSchema(state);\n this.#appender = new MongoAppend(state);\n this.#claims = new MongoClaims(state, { laneLeases, ordering, queries });\n this.#laneLeases = laneLeases;\n this.#completion = new MongoCompletion(state);\n this.#queries = queries;\n this.#purger = new MongoPurge(state);\n }\n\n /**\n * Verifies the deployment supports transactions, creates the collections and\n * indexes and seeds the lane documents. Upgrades a 0.1.0 database in place\n * first (see `MongoSchema.#upgradeFromVersion010`); the seeded lanes\n * mark the upgrade as done, so later runs skip it. Safe to run repeatedly and\n * from several processes. Stop 0.1.0 workers before the first run.\n *\n * @throws ConfigurationError when the server is a standalone mongod.\n */\n setup(): Promise<void> {\n return this.#schema.setup();\n }\n\n /**\n * Runs `work` in a transaction on a new session and commits when it resolves.\n *\n * `work` can run more than once. The driver restarts the whole callback after\n * a transient failure such as a write conflict, and re-sends only the commit\n * after an unknown commit result. A restart is safe for everything written\n * through the session, because the aborted attempt left nothing behind. It is\n * not safe for side effects outside the session (HTTP calls, other databases),\n * so keep those out of `work`; relaybus handlers are already at-least-once.\n *\n * With `options.timeoutMs` (from `bus.transaction`) the server bounds the commit with\n * `maxCommitTimeMS`; the bus aborts a transaction that ran past the budget before its commit.\n *\n * @throws ConfigurationError when the deployment does not support transactions.\n */\n transaction<T>(\n work: (transaction: ClientSession) => Promise<T>,\n options?: EventStoreTransactionOptions,\n ): Promise<T> {\n return options === undefined\n ? runInTransaction(this.#state, work)\n : runInBudgetedTransaction(this.#state, { work, timeoutMs: options.timeoutMs });\n }\n\n /**\n * Writes the entries in `session`. An existing event gets a delivery only for\n * handlers it does not list yet; the added handlers are appended to its list\n * together with a `revision` increment, a real write that makes a concurrent\n * purge of the event conflict with this transaction.\n */\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n append(\n session: ClientSession,\n entries: readonly AppendEntry[],\n now: Date,\n ): Promise<AppendResult> {\n return this.#appender.append(session, { entries, now });\n }\n\n /**\n * Claims up to `limit` due deliveries. It claims from the lanes this owner\n * (and this store instance) holds under a live lease first, then takes free\n * lanes with due work, a few at a time (4, 8, 16, ...) and the lane with the\n * oldest due delivery first, so a worker holds only as many lanes as it\n * needs. It then records the batch with one write per lane and hands back the\n * lanes that yielded nothing and run nothing. No delivery document is\n * written, except for the attempt charged to deliveries of a lane taken over\n * and for parking (see `MongoOrdering.#parkDeliveries`).\n *\n * Taking a lane is one conditional `findOneAndUpdate` that also moves the\n * previous owner's in-flight list to the lane's `lost` list; a lane another\n * claimer took first is skipped, never waited for. Lost deliveries are charged\n * one attempt before anything is read from the lane, and `lost` is cleared\n * only after that. Whoever holds the lane next charges a `lost` list it finds\n * first, so a claim that fails anywhere after the take loses no charge; the\n * charge of a lost claim is recorded on the delivery, so charging the list\n * again after a failure before the clear charges nothing twice.\n * Nothing a failed claim did leaves a delivery listed as running.\n */\n claim(request: ClaimRequest): Promise<ClaimedDelivery[]> {\n return this.#claims.claim(request);\n }\n\n /**\n * Extends the lease of the lane a running delivery belongs to. The lane lease\n * never shrinks, so a repeated renewal with the same value still holds. An\n * expired lease nobody took over is still renewed, so `_now` is not needed.\n */\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n extendLease(lease: LeaseReference, leaseExpiresAt: Date, _now?: Date): Promise<boolean> {\n return this.#completion.extendLease(lease, leaseExpiresAt);\n }\n\n /**\n * Deletes the delivery (and records it in the completion history, when kept).\n * With `session` the deletion commits with the caller's transaction; without,\n * it runs in a transaction of its own. Returns false when the lease was lost.\n */\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n complete(lease: LeaseReference, now: Date, session?: ClientSession): Promise<boolean> {\n return this.#completion.complete(lease, { now, session });\n }\n\n /**\n * Completes many leases with a fixed number of round trips, whatever lanes\n * they belong to: three commands without a completion history, one\n * transaction with it (see `MongoCompletion.#deleteFenced`).\n * Returns one flag per lease in input order; a lease listed twice completes\n * once, and a token this store cannot have issued is refused.\n */\n completeMany(leases: readonly LeaseReference[], now: Date): Promise<boolean[]> {\n return this.#completion.completeMany(leases, now);\n }\n\n /** Returns a running delivery to pending, due at `availableAt`, and counts the attempt that ended. */\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n reschedule(\n lease: LeaseReference,\n availableAt: Date,\n error: ErrorInfo,\n now: Date,\n ): Promise<boolean> {\n return this.#completion.reschedule(lease, { availableAt, error, now });\n }\n\n /** Gives a running delivery back without counting the attempt: pending, due `now`. */\n release(lease: LeaseReference, now: Date): Promise<boolean> {\n return this.#completion.release(lease, now);\n }\n\n /** Moves a running delivery to dead and counts the attempt that ended. */\n // eslint-disable-next-line relaybus/max-two-params -- EventStore port signature\n bury(lease: LeaseReference, error: ErrorInfo, now: Date): Promise<boolean> {\n return this.#completion.bury(lease, { error, now });\n }\n\n /**\n * Frees every lane `leaseOwner` holds that runs no delivery, so other workers\n * need not wait for the lease to expire. Lanes with running deliveries stay leased.\n */\n relinquish(leaseOwner: string): Promise<void> {\n return this.#laneLeases.relinquish(leaseOwner);\n }\n\n /**\n * Lists deliveries in creation order. A delivery is `processing` while its\n * document exists as `pending` and its lane lists it; its attempt count then\n * includes the running attempt, and owner and expiry are those of the lane\n * lease. Completion history records (when kept) are listed as `completed`.\n */\n listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]> {\n return this.#queries.listDeliveries(query);\n }\n\n /** Moves dead deliveries back to pending with a fresh attempt budget. */\n requeue(deliveryIds: readonly string[], now: Date): Promise<number> {\n return this.#queries.requeue(deliveryIds, now);\n }\n\n /**\n * Deletes, in batches of `purgeBatchSize`, dead deliveries last updated before\n * `deadBefore`, and completion history records (and `completed` documents left\n * by 0.1.0) completed before `completedBefore`, each batch in one transaction\n * together with the events it left without any reference. Finally, events\n * nothing references are deleted: one with a completed delivery once its last\n * completion is before `completedBefore` (never by `deadBefore` alone), one\n * that never had a completion (no subscribers, or only dead letters) once it\n * was created before the earliest given cutoff. The batch step applies the\n * same rule to events whose last completion is recorded.\n */\n purge(request: PurgeRequest): Promise<PurgeResult> {\n return this.#purger.purge(request);\n }\n\n /**\n * Counts by derived status. `pending` excludes running deliveries; `completed`\n * counts history records and 0.1.0 `completed` documents. `oldestDueAt` is the\n * oldest instant at which a delivery became claimable: the due time of a\n * pending delivery nobody runs, or the lease expiry of a lane that still runs\n * deliveries.\n */\n statistics(now: Date): Promise<EventStoreStatistics> {\n return this.#queries.statistics(now);\n }\n}\n"]}
|