@ahrowe/mongo 0.0.1

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/dist/db.js ADDED
@@ -0,0 +1,390 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { MongoClient, ObjectId, } from 'mongodb';
3
+ import { EventEmitter } from 'node:events';
4
+ import _ from 'lodash';
5
+ import { batchify } from './batchify.js';
6
+ import { OUTBOX_COLLECTION, OutboxOp, OutboxStatus } from './types/outbox.js';
7
+ const logger = {
8
+ debug: console.debug,
9
+ info: console.info,
10
+ warn: console.warn,
11
+ error: console.error,
12
+ };
13
+ let client;
14
+ let readClient;
15
+ let db;
16
+ let readDb;
17
+ const connectionBus = new EventEmitter();
18
+ let contextProvider = null;
19
+ export const setOutboxContextProvider = (fn) => {
20
+ contextProvider = fn;
21
+ };
22
+ /** collectionName → the service's in-process EventEmitter (the relay's routing table). */
23
+ const serviceBusRegistry = new Map();
24
+ export const getServiceBus = (collectionName) => serviceBusRegistry.get(collectionName);
25
+ export const getRegisteredCollections = () => [...serviceBusRegistry.keys()];
26
+ /** Raw outbox collection — used by the relay to claim/mark rows WITHOUT emitting. */
27
+ export const getOutboxCollection = () => db.collection(OUTBOX_COLLECTION);
28
+ /** Drop updatedOn before comparing — skip events when only that field changed. */
29
+ const stripNoise = (doc) => _.omit(doc, ['updatedOn']);
30
+ async function enqueueOutbox(collectionName, session, rows) {
31
+ if (!rows.length)
32
+ return;
33
+ const context = contextProvider ? contextProvider() ?? null : null;
34
+ const now = new Date();
35
+ const outboxRows = rows.map((r) => ({
36
+ _id: new ObjectId().toHexString(),
37
+ collectionName,
38
+ op: r.op,
39
+ doc: r.doc,
40
+ prevDoc: r.prevDoc ?? null,
41
+ meta: r.meta ?? null,
42
+ context,
43
+ status: OutboxStatus.Pending,
44
+ attempts: 0,
45
+ nextAttemptAt: now,
46
+ leasedUntil: null,
47
+ leasedBy: null,
48
+ lastError: null,
49
+ createdOn: now,
50
+ processedOn: null,
51
+ }));
52
+ await db.collection(OUTBOX_COLLECTION).insertMany(outboxRows, { session });
53
+ }
54
+ // --- guardListener (connection bus only — relay handles listener errors per-row) ---
55
+ function guardListener(label, callback) {
56
+ return (...args) => {
57
+ try {
58
+ Promise.resolve(callback(...args)).catch((error) => {
59
+ logger.error(`Listener for ${label} rejected:`, error);
60
+ });
61
+ }
62
+ catch (error) {
63
+ logger.error(`Listener for ${label} threw:`, error);
64
+ }
65
+ };
66
+ }
67
+ const generateService = (collectionName, validate = null, { addCreatedOnField = true, addUpdatedOnField = true, maxLimit: serviceMaxLimit, maxBatchSize: serviceMaxBatchSize, emitOutboxEvents = true, } = {}) => {
68
+ const driver = db.collection(collectionName);
69
+ const readDriver = readDb.collection(collectionName);
70
+ const name = driver.collectionName;
71
+ const bus = new EventEmitter();
72
+ serviceBusRegistry.set(name, bus);
73
+ function validateSchema(entity) {
74
+ if (validate) {
75
+ const result = validate(entity);
76
+ if (result.error)
77
+ throw result.error;
78
+ }
79
+ return entity;
80
+ }
81
+ async function executeWithTransaction(functionToRun) {
82
+ return client.withSession(async (session) => {
83
+ return session.withTransaction(async () => {
84
+ return functionToRun(session);
85
+ });
86
+ });
87
+ }
88
+ function getUpdateBodyWithUpdatedOn(updateBody) {
89
+ if (!addUpdatedOnField)
90
+ return updateBody;
91
+ const updatedSet = { $set: { updatedOn: new Date() } };
92
+ if (Array.isArray(updateBody))
93
+ return [...updateBody, updatedSet];
94
+ if (updateBody.$set)
95
+ return { ...updateBody, $set: { ...updateBody.$set, updatedOn: new Date() } };
96
+ return { ...updateBody, ...updatedSet };
97
+ }
98
+ function generateId() {
99
+ return new ObjectId().toHexString();
100
+ }
101
+ // on() registers listeners on the in-process bus. The relay dispatches to them
102
+ // and handles per-row errors itself — do NOT wrap with guardListener here, as
103
+ // that would swallow errors before the relay's retry/dead-letter logic sees them.
104
+ function on(eventName, callback) {
105
+ logger.debug(`Called "on" for collection "${name}"\nEvent: ${eventName}`);
106
+ return bus.on(eventName, callback);
107
+ }
108
+ function onPropertiesUpdated(properties, callback) {
109
+ return on('updated', (evt) => {
110
+ const newData = evt.doc;
111
+ const prevData = evt.prevDoc;
112
+ const hasListedPropertyChanged = !_.isEqual(_.pick(newData, properties), _.pick(prevData, properties));
113
+ if (hasListedPropertyChanged)
114
+ callback(evt);
115
+ });
116
+ }
117
+ function findCursor(query, options = {}) {
118
+ const limit = options.maxLimit ?? serviceMaxLimit;
119
+ if (limit !== undefined && (options?.limit || 0) > limit) {
120
+ throw new Error(`findCursor: Limit is higher than ${limit}\nQuery: ${JSON.stringify(query)}\nOptions: ${JSON.stringify(options)}`);
121
+ }
122
+ const { preferReadFromSecondary } = options;
123
+ const findOptions = _.omit(options, ['preferReadFromSecondary', 'maxLimit']);
124
+ return preferReadFromSecondary ? readDriver.find(query, findOptions) : driver.find(query, findOptions);
125
+ }
126
+ async function find(query, options = {}) {
127
+ return findCursor(query, options).toArray();
128
+ }
129
+ async function findOne(query, options = {}) {
130
+ const limit = 2;
131
+ const found = await findCursor(query, { ...options, limit }).toArray();
132
+ if (found.length > 1)
133
+ throw new Error(`findOne: More than one document return for query ${JSON.stringify(query)}`);
134
+ return found?.[0] || null;
135
+ }
136
+ // Core single-document update: read before, atomic write, validate. Shared by
137
+ // updateOne and updateMany's per-document reliable path.
138
+ async function performSingleUpdate(query, updateBody, session, options = {}) {
139
+ const preUpdate = await findOne(query, { session });
140
+ const enhancedUpdateBody = getUpdateBodyWithUpdatedOn(updateBody);
141
+ const postUpdate = await driver.findOneAndUpdate(query, enhancedUpdateBody, {
142
+ ...options,
143
+ returnDocument: 'after',
144
+ session,
145
+ });
146
+ if (!postUpdate)
147
+ return { preUpdate: null, postUpdate: null };
148
+ if (!options.skipValidation)
149
+ validateSchema(postUpdate);
150
+ return { preUpdate: preUpdate ?? null, postUpdate: postUpdate };
151
+ }
152
+ async function updateOne(query, updateBody, options = {}) {
153
+ if ('upsert' in options)
154
+ throw new Error('updateOne: upsert option is not allowed. Use insert method instead.');
155
+ if (!emitOutboxEvents) {
156
+ // Lean path: no pre-read, no outbox row. findOneAndUpdate is atomic by itself.
157
+ const enhancedUpdateBody = getUpdateBodyWithUpdatedOn(updateBody);
158
+ const run = async (session) => {
159
+ const result = await driver.findOneAndUpdate(query, enhancedUpdateBody, {
160
+ ...options,
161
+ returnDocument: options.returnOriginal ? 'before' : 'after',
162
+ session,
163
+ });
164
+ if (!result)
165
+ return null;
166
+ if (!options.skipValidation)
167
+ validateSchema(result);
168
+ return result;
169
+ };
170
+ if (options.session)
171
+ return run(options.session);
172
+ return executeWithTransaction(run);
173
+ }
174
+ const baseUpdateLogic = async (session) => {
175
+ const { preUpdate, postUpdate } = await performSingleUpdate(query, updateBody, session, options);
176
+ if (preUpdate && postUpdate && !_.isEqual(stripNoise(preUpdate), stripNoise(postUpdate))) {
177
+ await enqueueOutbox(name, session, [{ op: OutboxOp.Updated, doc: postUpdate, prevDoc: preUpdate, meta: options.meta }]);
178
+ }
179
+ return { preUpdate, postUpdate };
180
+ };
181
+ const { preUpdate, postUpdate } = options.session
182
+ ? await baseUpdateLogic(options.session)
183
+ : await executeWithTransaction(baseUpdateLogic);
184
+ return options.returnOriginal ? preUpdate : postUpdate;
185
+ }
186
+ async function updateMany(query, updateBody, options = {}) {
187
+ if ('upsert' in options)
188
+ throw new Error('updateMany: upsert option is not allowed. Use insert method instead.');
189
+ const skipValidation = options.skipValidation ?? false;
190
+ if (!emitOutboxEvents) {
191
+ // Fast path: no outbox rows needed — single native bulk write, one sampled doc validated.
192
+ const baseLogic = async (session) => {
193
+ const entitiesPreUpdate = skipValidation ? [] : await find(query, { ...options, session, limit: 1, projection: { _id: 1 } });
194
+ const enhancedUpdateBody = getUpdateBodyWithUpdatedOn(updateBody);
195
+ const updateManyRes = await driver.updateMany(query, enhancedUpdateBody, { ...options, session });
196
+ if (!skipValidation && entitiesPreUpdate.length > 0) {
197
+ const entityPostUpdate = await findOne({ _id: entitiesPreUpdate[0]._id }, { session });
198
+ validateSchema(entityPostUpdate);
199
+ }
200
+ return updateManyRes;
201
+ };
202
+ const res = options.session ? await baseLogic(options.session) : await executeWithTransaction(baseLogic);
203
+ return { ...res, nModified: res.modifiedCount };
204
+ }
205
+ // Reliable path: per-document atomic ops inside one transaction so the whole
206
+ // batch rolls back together. Every document is individually validated and gets
207
+ // an accurate {prevDoc, doc} pair — not a diff between two independent scans.
208
+ // No cap by default — pass maxBatchSize (per-call or via createService) to
209
+ // enforce one, recommended once batches risk hitting MongoDB's transaction lifetime limit.
210
+ const maxBatchSize = options.maxBatchSize ?? serviceMaxBatchSize;
211
+ const baseReliableLogic = async (session) => {
212
+ const matchedCount = await driver.countDocuments(query, { session });
213
+ if (maxBatchSize !== undefined && matchedCount > maxBatchSize) {
214
+ throw new Error(`updateMany: matched ${matchedCount} documents, which exceeds the limit of ${maxBatchSize}. A single transaction processing this many documents risks hitting MongoDB's transaction lifetime limit.\nQuery: ${JSON.stringify(query)}\nUse bulkWrite for larger batch updates (no transaction/validation/event guarantees), or raise maxBatchSize.`);
215
+ }
216
+ const matchedIds = (await find(query, { session, projection: { _id: 1 }, sort: { _id: 1 } }));
217
+ let modifiedCount = 0;
218
+ await batchify({
219
+ dataDelivery: matchedIds,
220
+ batchSize: 100,
221
+ concurrency: 1,
222
+ throwOnError: true,
223
+ functionToRun: async ({ _id }) => {
224
+ const { preUpdate, postUpdate } = await performSingleUpdate({ _id }, updateBody, session, { skipValidation });
225
+ if (postUpdate) {
226
+ modifiedCount += 1;
227
+ if (preUpdate && !_.isEqual(stripNoise(preUpdate), stripNoise(postUpdate))) {
228
+ await enqueueOutbox(name, session, [{ op: OutboxOp.Updated, doc: postUpdate, prevDoc: preUpdate, meta: options.meta }]);
229
+ }
230
+ }
231
+ },
232
+ });
233
+ return { matchedCount, modifiedCount };
234
+ };
235
+ const { matchedCount, modifiedCount } = options.session
236
+ ? await baseReliableLogic(options.session)
237
+ : await executeWithTransaction(baseReliableLogic);
238
+ return { acknowledged: true, matchedCount, modifiedCount, nModified: modifiedCount, upsertedCount: 0, upsertedId: null };
239
+ }
240
+ async function removeOne(query, options = {}) {
241
+ if (!emitOutboxEvents)
242
+ return driver.findOneAndDelete(query, options);
243
+ const baseLogic = async (session) => {
244
+ const removed = await driver.findOneAndDelete(query, { ...options, session });
245
+ if (removed)
246
+ await enqueueOutbox(name, session, [{ op: OutboxOp.Removed, doc: removed, meta: options.meta }]);
247
+ return removed;
248
+ };
249
+ if (options.session)
250
+ return baseLogic(options.session);
251
+ return executeWithTransaction(baseLogic);
252
+ }
253
+ async function removeMany(query, options = {}) {
254
+ const returnRemoved = options.returnRemoved ?? true;
255
+ if (!emitOutboxEvents) {
256
+ const entriesToRemove = returnRemoved ? await find(query, options) : undefined;
257
+ const deleteRes = await driver.deleteMany(query, options);
258
+ return { ...deleteRes, results: entriesToRemove };
259
+ }
260
+ // Reliable path: per-document atomic deletes inside one transaction.
261
+ const maxBatchSize = options.maxBatchSize ?? serviceMaxBatchSize;
262
+ const baseReliableLogic = async (session) => {
263
+ const matchedCount = await driver.countDocuments(query, { session });
264
+ if (maxBatchSize !== undefined && matchedCount > maxBatchSize) {
265
+ throw new Error(`removeMany: matched ${matchedCount} documents, which exceeds the limit of ${maxBatchSize}. A single transaction processing this many documents risks hitting MongoDB's transaction lifetime limit.\nQuery: ${JSON.stringify(query)}\nUse bulkWrite for larger batch removals (no transaction/event guarantees), or raise maxBatchSize.`);
266
+ }
267
+ const matchedIds = (await find(query, { session, projection: { _id: 1 }, sort: { _id: 1 } }));
268
+ const removed = [];
269
+ await batchify({
270
+ dataDelivery: matchedIds,
271
+ batchSize: 100,
272
+ concurrency: 1,
273
+ throwOnError: true,
274
+ functionToRun: async ({ _id }) => {
275
+ const deletedDoc = await driver.findOneAndDelete({ _id }, { session });
276
+ if (deletedDoc) {
277
+ removed.push(deletedDoc);
278
+ await enqueueOutbox(name, session, [{ op: OutboxOp.Removed, doc: deletedDoc, meta: options.meta }]);
279
+ }
280
+ },
281
+ });
282
+ return { matchedCount, removed };
283
+ };
284
+ const { removed } = options.session
285
+ ? await baseReliableLogic(options.session)
286
+ : await executeWithTransaction(baseReliableLogic);
287
+ return { acknowledged: true, deletedCount: removed.length, results: returnRemoved ? removed : undefined };
288
+ }
289
+ async function insert(entitiesToCreate, options = {}) {
290
+ const isMultiInsert = Array.isArray(entitiesToCreate);
291
+ const newEntities = isMultiInsert ? entitiesToCreate : [entitiesToCreate];
292
+ const preInsert = (entity) => ({
293
+ ...entity,
294
+ _id: entity._id || generateId(),
295
+ ...(addCreatedOnField ? { createdOn: entity.createdOn || new Date() } : {}),
296
+ });
297
+ const validateFunction = options.skipValidation ? (e) => e : validateSchema;
298
+ const baseInsertLogic = async (session) => {
299
+ const parsedEntities = newEntities.map((entity) => validateFunction(preInsert(entity)));
300
+ await driver.insertMany(parsedEntities, { ...options, session });
301
+ if (emitOutboxEvents) {
302
+ await enqueueOutbox(name, session, parsedEntities.map((doc) => ({ op: OutboxOp.Created, doc, meta: options.meta })));
303
+ }
304
+ return isMultiInsert ? parsedEntities : parsedEntities[0];
305
+ };
306
+ return options.session ? baseInsertLogic(options.session) : executeWithTransaction(baseInsertLogic);
307
+ }
308
+ async function count(query, options = {}) {
309
+ return options.preferReadFromSecondary ? readDriver.countDocuments(query) : driver.countDocuments(query);
310
+ }
311
+ async function exists(query) {
312
+ return !!(await find(query, { limit: 1, projection: { _id: 1 } })).length;
313
+ }
314
+ async function aggregate(pipeline = [], options = {}) {
315
+ const { preferReadFromSecondary, ...aggOptions } = options;
316
+ return (preferReadFromSecondary ? readDriver : driver).aggregate(pipeline, aggOptions).toArray();
317
+ }
318
+ async function distinct(field, query, options = {}) {
319
+ return driver.distinct(field, query, options);
320
+ }
321
+ async function createIndex(fields, options = {}) {
322
+ const background = options.background ?? true;
323
+ return driver.createIndex(fields, { ...options, background });
324
+ }
325
+ async function bulkWrite(operations, options = {}) {
326
+ if (!options.allowBulkwrite)
327
+ throw new Error('Bulkwrite not allowed');
328
+ return driver.bulkWrite(operations, options);
329
+ }
330
+ return {
331
+ find,
332
+ findCursor,
333
+ findOne,
334
+ updateOne,
335
+ updateMany,
336
+ removeOne,
337
+ removeMany,
338
+ insert,
339
+ count,
340
+ exists,
341
+ aggregate,
342
+ generateId,
343
+ distinct,
344
+ name,
345
+ createIndex,
346
+ on,
347
+ onPropertiesUpdated,
348
+ eventBus: bus,
349
+ bulkWrite,
350
+ };
351
+ };
352
+ const createService = (collectionName, validate = null, options = {}) => generateService(collectionName, validate, options);
353
+ function wireConnectionEvents(mongoClient, source) {
354
+ mongoClient.on('error', (error) => {
355
+ logger.error(`MongoDB ${source} client error:`, error);
356
+ connectionBus.emit('error', { source, error });
357
+ });
358
+ mongoClient.on('close', (error) => {
359
+ if (error)
360
+ logger.error(`MongoDB ${source} connection lost:`, error);
361
+ connectionBus.emit('close', { source, error });
362
+ });
363
+ }
364
+ const connect = (connectionString, databaseName) => {
365
+ if (!client) {
366
+ logger.info('MongoDB connecting');
367
+ client = new MongoClient(connectionString);
368
+ db = client.db(databaseName);
369
+ wireConnectionEvents(client, 'primary');
370
+ logger.info('MongoDB connecting to readClient');
371
+ const separator = connectionString.includes('?') ? '&' : '?';
372
+ readClient = new MongoClient(`${connectionString}${separator}readPreference=secondaryPreferred&maxStalenessSeconds=120`);
373
+ readDb = readClient.db(databaseName);
374
+ wireConnectionEvents(readClient, 'read');
375
+ }
376
+ return {
377
+ createService,
378
+ on: (eventName, callback) => connectionBus.on(eventName, guardListener(`"${eventName}" on the connection`, callback)),
379
+ };
380
+ };
381
+ export const disconnect = async () => {
382
+ await Promise.allSettled([client?.close(), readClient?.close()].filter(Boolean));
383
+ client = undefined;
384
+ readClient = undefined;
385
+ };
386
+ export { connect, createService };
387
+ export const withSession = async (callback) => client.withSession(callback);
388
+ export const startSession = async (options) => client.startSession(options);
389
+ export default { connect, createService, withSession, startSession, disconnect };
390
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { connect, createService, withSession, startSession, disconnect, setOutboxContextProvider, getServiceBus, getRegisteredCollections, getOutboxCollection, type DbService, } from './db.js';
2
+ export { default } from './db.js';
3
+ export { startOutboxRelay, type OutboxRelay, type OutboxRelayOptions } from './outboxRelay.js';
4
+ export { OUTBOX_COLLECTION, OutboxOp, OutboxStatus, type OutboxRow } from './types/outbox.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,UAAU,EACV,wBAAwB,EACxB,aAAa,EACb,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,SAAS,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { connect, createService, withSession, startSession, disconnect, setOutboxContextProvider, getServiceBus, getRegisteredCollections, getOutboxCollection, } from './db.js';
2
+ export { default } from './db.js';
3
+ export { startOutboxRelay } from './outboxRelay.js';
4
+ export { OUTBOX_COLLECTION, OutboxOp, OutboxStatus } from './types/outbox.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,UAAU,EACV,wBAAwB,EACxB,aAAa,EACb,wBAAwB,EACxB,mBAAmB,GAEpB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAA6C,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,EAAkB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,34 @@
1
+ export interface OutboxRelayOptions {
2
+ /** Unique per process/pod — identifies the lease holder so stale claims can be reclaimed. */
3
+ instanceId: string;
4
+ /** Idle poll interval when the outbox is empty (ms). Default 500. */
5
+ pollIntervalMs?: number;
6
+ /** Max rows claimed+dispatched per tick. Default 20. */
7
+ batchSize?: number;
8
+ /** How long a claim is held before another instance may reclaim it (ms). Default 30_000. */
9
+ leaseMs?: number;
10
+ /** Attempts before a row is dead-lettered to `failed`. Default 10. */
11
+ maxAttempts?: number;
12
+ /** Backoff before a failed row becomes claimable again (ms). Default capped exponential. */
13
+ backoffMs?: (attempt: number) => number;
14
+ /** Start the background poll loop immediately (default true). Set false to drive `tick`/`drain` manually (tests). */
15
+ autoStart?: boolean;
16
+ }
17
+ export interface OutboxRelay {
18
+ /** Stop the background loop, finish the in-flight tick, release rows this instance holds. */
19
+ stop: () => Promise<void>;
20
+ /** Run a single claim+dispatch batch; returns how many rows it processed. */
21
+ tick: () => Promise<number>;
22
+ /** Process pending rows until none are claimable; returns total processed. (Mainly for tests.) */
23
+ drain: () => Promise<number>;
24
+ }
25
+ /**
26
+ * Drains the transactional outbox and dispatches each event to the in-process
27
+ * listeners registered on its source collection's bus.
28
+ *
29
+ * Restart-safe and multi-pod-safe: rows are claimed with an atomic
30
+ * findOneAndUpdate + a lease, stale leases are reclaimed, and delivery is
31
+ * at-least-once (consumers must be idempotent).
32
+ */
33
+ export declare const startOutboxRelay: (options: OutboxRelayOptions) => OutboxRelay;
34
+ //# sourceMappingURL=outboxRelay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outboxRelay.d.ts","sourceRoot":"","sources":["../src/outboxRelay.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,qHAAqH;IACrH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,6FAA6F;IAC7F,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,6EAA6E;IAC7E,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,kGAAkG;IAClG,KAAK,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9B;AAMD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,kBAAkB,KAAG,WA+J9D,CAAC"}
@@ -0,0 +1,152 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { getOutboxCollection, getServiceBus } from './db.js';
3
+ import { OutboxStatus } from './types/outbox.js';
4
+ const logger = {
5
+ info: console.info,
6
+ warn: console.warn,
7
+ error: console.error,
8
+ };
9
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
10
+ const defaultBackoff = (attempt) => Math.min(30000, 1000 * 2 ** Math.max(0, attempt - 1));
11
+ /**
12
+ * Drains the transactional outbox and dispatches each event to the in-process
13
+ * listeners registered on its source collection's bus.
14
+ *
15
+ * Restart-safe and multi-pod-safe: rows are claimed with an atomic
16
+ * findOneAndUpdate + a lease, stale leases are reclaimed, and delivery is
17
+ * at-least-once (consumers must be idempotent).
18
+ */
19
+ export const startOutboxRelay = (options) => {
20
+ const { instanceId, pollIntervalMs = 500, batchSize = 20, leaseMs = 30000, maxAttempts = 10, backoffMs = defaultBackoff, autoStart = true, } = options;
21
+ let running = true;
22
+ let loopPromise = null;
23
+ let indexesReady = null;
24
+ const ensureIndexes = () => {
25
+ if (!indexesReady) {
26
+ const col = getOutboxCollection();
27
+ indexesReady = Promise.all([
28
+ col.createIndex({ status: 1, nextAttemptAt: 1, leasedUntil: 1 }, { background: true }),
29
+ // TTL: drop completed rows a week after processing. Failed rows keep processedOn null
30
+ // so they are NOT expired — they must be inspected/replayed manually.
31
+ col.createIndex({ processedOn: 1 }, { background: true, expireAfterSeconds: 60 * 60 * 24 * 7 }),
32
+ ]).then(() => undefined);
33
+ }
34
+ return indexesReady;
35
+ };
36
+ const claimOne = async () => {
37
+ const col = getOutboxCollection();
38
+ const now = new Date();
39
+ const claimed = await col.findOneAndUpdate({
40
+ $or: [
41
+ { status: OutboxStatus.Pending, nextAttemptAt: { $lte: now } },
42
+ { status: OutboxStatus.Processing, leasedUntil: { $lt: now } },
43
+ ],
44
+ }, {
45
+ $set: {
46
+ status: OutboxStatus.Processing,
47
+ leasedBy: instanceId,
48
+ leasedUntil: new Date(now.getTime() + leaseMs),
49
+ },
50
+ $inc: { attempts: 1 },
51
+ }, { sort: { createdOn: 1 }, returnDocument: 'after' });
52
+ return claimed ?? null;
53
+ };
54
+ const dispatch = async (row) => {
55
+ const bus = getServiceBus(row.collectionName);
56
+ if (!bus)
57
+ return;
58
+ const payload = {
59
+ prevDoc: row.prevDoc ?? undefined,
60
+ doc: row.doc,
61
+ meta: row.meta ?? undefined,
62
+ context: row.context ?? undefined,
63
+ eventId: row._id,
64
+ };
65
+ const listeners = bus.listeners(row.op);
66
+ await Promise.all(listeners.map(async (l) => l(payload)));
67
+ };
68
+ const markDone = async (row) => {
69
+ await getOutboxCollection().updateOne({ _id: row._id }, { $set: { status: OutboxStatus.Done, processedOn: new Date(), lastError: null, leasedBy: null, leasedUntil: null } });
70
+ };
71
+ const markFailure = async (row, err) => {
72
+ const message = err instanceof Error ? err.message : String(err);
73
+ if (row.attempts >= maxAttempts) {
74
+ await getOutboxCollection().updateOne({ _id: row._id }, { $set: { status: OutboxStatus.Failed, lastError: message, leasedBy: null, leasedUntil: null } });
75
+ logger.error(`Outbox row ${row._id} (${row.collectionName}/${row.op}) dead-lettered after ${row.attempts} attempts: ${message}`);
76
+ }
77
+ else {
78
+ await getOutboxCollection().updateOne({ _id: row._id }, {
79
+ $set: {
80
+ status: OutboxStatus.Pending,
81
+ nextAttemptAt: new Date(Date.now() + backoffMs(row.attempts)),
82
+ lastError: message,
83
+ leasedBy: null,
84
+ leasedUntil: null,
85
+ },
86
+ });
87
+ logger.warn(`Outbox row ${row._id} (${row.collectionName}/${row.op}) failed (attempt ${row.attempts}), will retry: ${message}`);
88
+ }
89
+ };
90
+ const processRow = async (row) => {
91
+ try {
92
+ await dispatch(row);
93
+ await markDone(row);
94
+ }
95
+ catch (err) {
96
+ await markFailure(row, err);
97
+ }
98
+ };
99
+ const tick = async () => {
100
+ await ensureIndexes();
101
+ let processed = 0;
102
+ for (let i = 0; i < batchSize; i += 1) {
103
+ const row = await claimOne();
104
+ if (!row)
105
+ break;
106
+ await processRow(row);
107
+ processed += 1;
108
+ }
109
+ return processed;
110
+ };
111
+ const drain = async () => {
112
+ let total = 0;
113
+ for (;;) {
114
+ const n = await tick();
115
+ if (n === 0)
116
+ return total;
117
+ total += n;
118
+ }
119
+ };
120
+ const loop = async () => {
121
+ while (running) {
122
+ let processed = 0;
123
+ try {
124
+ processed = await tick();
125
+ }
126
+ catch (err) {
127
+ logger.error('Outbox relay tick failed:', err);
128
+ }
129
+ if (!running)
130
+ break;
131
+ if (processed === 0)
132
+ await sleep(pollIntervalMs);
133
+ }
134
+ };
135
+ const stop = async () => {
136
+ running = false;
137
+ if (loopPromise)
138
+ await loopPromise;
139
+ try {
140
+ await getOutboxCollection().updateMany({ status: OutboxStatus.Processing, leasedBy: instanceId }, { $set: { status: OutboxStatus.Pending, leasedBy: null, leasedUntil: null } });
141
+ }
142
+ catch (err) {
143
+ logger.error('Outbox relay failed to release leased rows on stop:', err);
144
+ }
145
+ };
146
+ if (autoStart) {
147
+ logger.info(`Outbox relay started (instance ${instanceId})`);
148
+ loopPromise = loop();
149
+ }
150
+ return { stop, tick, drain };
151
+ };
152
+ //# sourceMappingURL=outboxRelay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outboxRelay.js","sourceRoot":"","sources":["../src/outboxRelay.ts"],"names":[],"mappings":"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"}