@quave/agenda-mongodb 1.0.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.
Files changed (52) hide show
  1. package/LICENSE.md +25 -0
  2. package/README.md +273 -0
  3. package/dist/MongoBackend.d.ts +58 -0
  4. package/dist/MongoBackend.js +82 -0
  5. package/dist/MongoBackend.js.map +1 -0
  6. package/dist/MongoChangeStreamNotificationChannel.d.ts +96 -0
  7. package/dist/MongoChangeStreamNotificationChannel.js +248 -0
  8. package/dist/MongoChangeStreamNotificationChannel.js.map +1 -0
  9. package/dist/MongoJobLogger.d.ts +46 -0
  10. package/dist/MongoJobLogger.js +142 -0
  11. package/dist/MongoJobLogger.js.map +1 -0
  12. package/dist/MongoJobRepository.d.ts +84 -0
  13. package/dist/MongoJobRepository.js +713 -0
  14. package/dist/MongoJobRepository.js.map +1 -0
  15. package/dist/cjs/MongoBackend.d.ts +58 -0
  16. package/dist/cjs/MongoBackend.js +86 -0
  17. package/dist/cjs/MongoBackend.js.map +1 -0
  18. package/dist/cjs/MongoChangeStreamNotificationChannel.d.ts +96 -0
  19. package/dist/cjs/MongoChangeStreamNotificationChannel.js +255 -0
  20. package/dist/cjs/MongoChangeStreamNotificationChannel.js.map +1 -0
  21. package/dist/cjs/MongoJobLogger.d.ts +46 -0
  22. package/dist/cjs/MongoJobLogger.js +149 -0
  23. package/dist/cjs/MongoJobLogger.js.map +1 -0
  24. package/dist/cjs/MongoJobRepository.d.ts +84 -0
  25. package/dist/cjs/MongoJobRepository.js +720 -0
  26. package/dist/cjs/MongoJobRepository.js.map +1 -0
  27. package/dist/cjs/hasMongoProtocol.d.ts +1 -0
  28. package/dist/cjs/hasMongoProtocol.js +6 -0
  29. package/dist/cjs/hasMongoProtocol.js.map +1 -0
  30. package/dist/cjs/index.d.ts +39 -0
  31. package/dist/cjs/index.js +46 -0
  32. package/dist/cjs/index.js.map +1 -0
  33. package/dist/cjs/package.json +1 -0
  34. package/dist/cjs/testing.d.ts +25 -0
  35. package/dist/cjs/testing.js +55 -0
  36. package/dist/cjs/testing.js.map +1 -0
  37. package/dist/cjs/types.d.ts +52 -0
  38. package/dist/cjs/types.js +3 -0
  39. package/dist/cjs/types.js.map +1 -0
  40. package/dist/hasMongoProtocol.d.ts +1 -0
  41. package/dist/hasMongoProtocol.js +2 -0
  42. package/dist/hasMongoProtocol.js.map +1 -0
  43. package/dist/index.d.ts +39 -0
  44. package/dist/index.js +37 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/testing.d.ts +25 -0
  47. package/dist/testing.js +49 -0
  48. package/dist/testing.js.map +1 -0
  49. package/dist/types.d.ts +52 -0
  50. package/dist/types.js +2 -0
  51. package/dist/types.js.map +1 -0
  52. package/package.json +84 -0
package/LICENSE.md ADDED
@@ -0,0 +1,25 @@
1
+ ## License
2
+ (The MIT License)
3
+
4
+ Copyright (c) 2013 Ryan Schmukler <ryan@slingingcode.com>
5
+
6
+ Copyright (c) 2022-2026 Simon Tretter <s.tretter@gmail.com>
7
+
8
+ Contributors: Mikael Korpela, Alexis Tyler, Vasyl Boroviak, Haris Sulaiman, Loris Guignard
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
11
+ this software and associated documentation files (the 'Software'), to deal in
12
+ the Software without restriction, including without limitation the rights to
13
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
14
+ the Software, and to permit persons to whom the Software is furnished to do so,
15
+ subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
22
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
23
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,273 @@
1
+ # @quave/agenda-mongodb
2
+
3
+ > Quave-managed fork of [@agendajs/mongo-backend](https://github.com/agenda/agenda) (forked at `4.0.2`, commit `b9c47688`). MongoDB backend for [`@quave/agenda`](../agenda).
4
+
5
+ ## Runtime compatibility
6
+
7
+ - **mongodb driver**: `^4.17.0 || ^5.0.0 || ^6.0.0 || ^7.0.0` (peer dependency). Driver 4.17 is the line bundled with Meteor 2.x; the repository normalizes the `findOneAndUpdate` result-shape difference between driver 4/5 (ModifyResult) and 6/7 (document) automatically. Tests run against both driver 7.x and 4.17.
8
+ - **Node.js**: 14.13.1+ for the package itself (dual ESM + CommonJS builds, ES2020 target); your chosen mongodb driver sets its own floor (driver 6 needs Node 16.20+, driver 7 needs Node 20.19+).
9
+ - **Meteor 2.x**: supported — pass the app's existing driver-4 `Db` handle via `new MongoBackend({ mongo: db })`. CI runs a Meteor-style simulation (Node 14 + CommonJS + driver 4.17) on every push.
10
+
11
+ MongoDB backend for [Agenda](https://www.npmjs.com/package/agenda) job scheduler.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @quave/agenda @quave/agenda-mongodb
17
+ # or
18
+ pnpm add @quave/agenda @quave/agenda-mongodb
19
+ # or
20
+ yarn add @quave/agenda @quave/agenda-mongodb
21
+ ```
22
+
23
+ **Requirements:**
24
+ - Node.js 18+
25
+ - MongoDB 4+
26
+
27
+ ## Usage
28
+
29
+ ```typescript
30
+ import { Agenda } from '@quave/agenda';
31
+ import { MongoBackend } from '@quave/agenda-mongodb';
32
+
33
+ // Via connection string
34
+ const agenda = new Agenda({
35
+ backend: new MongoBackend({
36
+ address: 'mongodb://localhost/agenda'
37
+ })
38
+ });
39
+
40
+ // Or via existing MongoDB connection
41
+ import { MongoClient } from 'mongodb';
42
+
43
+ const client = await MongoClient.connect('mongodb://localhost');
44
+ const db = client.db('agenda');
45
+
46
+ const agenda = new Agenda({
47
+ backend: new MongoBackend({ mongo: db })
48
+ });
49
+
50
+ // Define jobs
51
+ agenda.define('send-email', async (job) => {
52
+ const { to, subject } = job.attrs.data;
53
+ await sendEmail(to, subject);
54
+ });
55
+
56
+ // Start processing
57
+ await agenda.start();
58
+
59
+ // Schedule jobs
60
+ await agenda.every('1 hour', 'send-email', { to: 'user@example.com', subject: 'Hello' });
61
+ ```
62
+
63
+ ## Configuration Options
64
+
65
+ ```typescript
66
+ interface IMongoBackendConfig {
67
+ /** MongoDB connection string */
68
+ address?: string;
69
+
70
+ /** Existing MongoDB database instance */
71
+ mongo?: Db;
72
+
73
+ /** Collection name for jobs (default: 'agendaJobs') */
74
+ collection?: string;
75
+
76
+ /** MongoDB client options */
77
+ options?: MongoClientOptions;
78
+
79
+ /** Name to identify this Agenda instance (stored as lastModifiedBy) */
80
+ name?: string;
81
+
82
+ /** Whether to create indexes on connect (default: true) */
83
+ ensureIndex?: boolean;
84
+
85
+ /** Sort order for job queries */
86
+ sort?: { [key: string]: SortDirection };
87
+ }
88
+ ```
89
+
90
+ ### Full Example with Options
91
+
92
+ ```typescript
93
+ const agenda = new Agenda({
94
+ backend: new MongoBackend({
95
+ address: 'mongodb://localhost/agenda',
96
+ collection: 'jobs', // Custom collection name
97
+ sort: { nextRunAt: 'asc', priority: 'desc' }
98
+ }),
99
+ processEvery: '30 seconds', // Job polling interval
100
+ maxConcurrency: 20, // Max concurrent jobs
101
+ defaultConcurrency: 5 // Default per job type
102
+ });
103
+ ```
104
+
105
+ ## Real-Time Notifications
106
+
107
+ MongoBackend provides storage only and uses polling to check for new jobs. For real-time job processing across distributed systems, you have several options:
108
+
109
+ ### Option 1: MongoDB Change Streams (Native)
110
+
111
+ If your MongoDB deployment is a replica set (even a single-node replica set works), you can use `MongoChangeStreamNotificationChannel` for native real-time notifications without any external dependencies:
112
+
113
+ ```typescript
114
+ import { Agenda } from '@quave/agenda';
115
+ import { MongoBackend, MongoChangeStreamNotificationChannel } from '@quave/agenda-mongodb';
116
+
117
+ const agenda = new Agenda({
118
+ backend: new MongoBackend({ mongo: db }),
119
+ notificationChannel: new MongoChangeStreamNotificationChannel({ db })
120
+ });
121
+
122
+ // Jobs are processed immediately when created (no polling delay)
123
+ await agenda.start();
124
+ await agenda.now('myJob'); // Triggers instant processing
125
+ ```
126
+
127
+ **Requirements:**
128
+ - MongoDB replica set (single-node replica sets work fine)
129
+ - WiredTiger storage engine (default since MongoDB 3.2)
130
+
131
+ **Configuration options:**
132
+ ```typescript
133
+ const channel = new MongoChangeStreamNotificationChannel({
134
+ db: mongoDb, // Required: MongoDB database instance
135
+ collection: 'agendaJobs', // Optional: collection name (default: 'agendaJobs')
136
+ resumeToken: savedToken, // Optional: resume from specific point
137
+ fullDocument: true // Optional: include full document on updates (default: true)
138
+ });
139
+ ```
140
+
141
+ ### Option 2: In-Memory (Single Process)
142
+
143
+ ```typescript
144
+ import { Agenda, InMemoryNotificationChannel } from '@quave/agenda';
145
+ import { MongoBackend } from '@quave/agenda-mongodb';
146
+
147
+ // For single-process apps (testing/development)
148
+ const agenda = new Agenda({
149
+ backend: new MongoBackend({ mongo: db }),
150
+ notificationChannel: new InMemoryNotificationChannel()
151
+ });
152
+ ```
153
+
154
+ ### Option 3: Redis Pub/Sub (Multi-Process)
155
+
156
+ ```typescript
157
+ import { Agenda } from '@quave/agenda';
158
+ import { MongoBackend } from '@quave/agenda-mongodb';
159
+ import { RedisBackend } from '@agendajs/redis-backend';
160
+
161
+ // For production: use Redis for notifications
162
+ const redisBackend = new RedisBackend({ connectionString: 'redis://localhost:6379' });
163
+ const agenda = new Agenda({
164
+ backend: new MongoBackend({ mongo: db }),
165
+ notificationChannel: redisBackend.notificationChannel
166
+ });
167
+ ```
168
+
169
+ ## Database Index
170
+
171
+ By default, MongoBackend automatically creates the `findAndLockNextJobIndex` index on connect for optimal job query performance. The index includes:
172
+
173
+ ```javascript
174
+ {
175
+ "name": 1,
176
+ "nextRunAt": 1,
177
+ "priority": -1,
178
+ "lockedAt": 1,
179
+ "disabled": 1
180
+ }
181
+ ```
182
+
183
+ To disable automatic index creation (e.g., if you manage indexes separately):
184
+
185
+ ```typescript
186
+ const backend = new MongoBackend({
187
+ mongo: db,
188
+ ensureIndex: false // Skip automatic index creation
189
+ });
190
+ ```
191
+
192
+ ### Additional Indexes
193
+
194
+ If you use **Agendash**, add this index for better dashboard performance:
195
+
196
+ ```javascript
197
+ db.agendaJobs.createIndex({
198
+ "nextRunAt": -1,
199
+ "lastRunAt": -1,
200
+ "lastFinishedAt": -1
201
+ }, { name: "agendash" })
202
+ ```
203
+
204
+ If you have job definitions with thousands of instances, this index can improve lock queries:
205
+
206
+ ```javascript
207
+ db.agendaJobs.createIndex({
208
+ "name": 1,
209
+ "disabled": 1,
210
+ "lockedAt": 1
211
+ }, { name: "findAndLockDeadJobs" })
212
+ ```
213
+
214
+ ## Job Logging
215
+
216
+ MongoBackend includes a built-in `MongoJobLogger` that stores structured job lifecycle events in a dedicated MongoDB collection (`agenda_logs` by default). The logger is lightweight and only creates its collection on first use.
217
+
218
+ ### Automatic Usage
219
+
220
+ When you enable logging in Agenda, the backend's built-in logger is used automatically:
221
+
222
+ ```typescript
223
+ const agenda = new Agenda({
224
+ backend: new MongoBackend({ mongo: db }),
225
+ logging: true // Uses MongoJobLogger automatically
226
+ });
227
+ ```
228
+
229
+ ### Standalone Usage
230
+
231
+ You can also use `MongoJobLogger` independently — for example, to log to MongoDB while using a different backend for storage:
232
+
233
+ ```typescript
234
+ import { MongoJobLogger } from '@quave/agenda-mongodb';
235
+
236
+ const logger = new MongoJobLogger({
237
+ mongo: db, // Required: MongoDB database instance
238
+ logCollection: 'agenda_logs' // Optional: collection name (default: 'agenda_logs')
239
+ });
240
+
241
+ // Use with any backend
242
+ import { RedisBackend } from '@agendajs/redis-backend';
243
+ const agenda = new Agenda({
244
+ backend: new RedisBackend({ connectionString: 'redis://...' }),
245
+ logging: logger
246
+ });
247
+ ```
248
+
249
+ ### Querying Logs
250
+
251
+ ```typescript
252
+ const { entries, total } = await agenda.getLogs({
253
+ jobName: 'send-email',
254
+ level: 'error',
255
+ limit: 50,
256
+ sort: 'desc'
257
+ });
258
+
259
+ // Clear old logs
260
+ await agenda.clearLogs({ to: new Date(Date.now() - 30 * 86400000) });
261
+ ```
262
+
263
+ See the [Agenda README](https://github.com/agenda/agenda#persistent-job-logging) for full logging documentation.
264
+
265
+ ## Related Packages
266
+
267
+ - [agenda](https://www.npmjs.com/package/agenda) - Core scheduler
268
+ - [@agendajs/postgres-backend](https://www.npmjs.com/package/@agendajs/postgres-backend) - PostgreSQL backend with LISTEN/NOTIFY
269
+ - [@agendajs/redis-backend](https://www.npmjs.com/package/@agendajs/redis-backend) - Redis backend with Pub/Sub
270
+
271
+ ## License
272
+
273
+ MIT
@@ -0,0 +1,58 @@
1
+ import type { AgendaBackend, JobRepository, NotificationChannel, JobLogger } from '@quave/agenda';
2
+ import type { MongoBackendConfig } from './types.js';
3
+ /**
4
+ * MongoDB backend for Agenda.
5
+ * Provides storage via MongoDB. Does not provide notifications (uses polling).
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { Agenda } from '@quave/agenda';
10
+ * import { MongoBackend } from '@quave/agenda-mongodb';
11
+ *
12
+ * // Via connection string
13
+ * const backend = new MongoBackend({ address: 'mongodb://localhost/agenda' });
14
+ *
15
+ * // Via existing connection
16
+ * const backend = new MongoBackend({ mongo: existingDb });
17
+ *
18
+ * // With persistent job event logging
19
+ * const backend = new MongoBackend({ mongo: existingDb, logging: true });
20
+ *
21
+ * const agenda = new Agenda({ backend, logging: true });
22
+ * ```
23
+ */
24
+ export declare class MongoBackend implements AgendaBackend {
25
+ private config;
26
+ readonly name = "MongoDB";
27
+ private _repository;
28
+ private _ownsConnection;
29
+ private _logger;
30
+ /**
31
+ * MongoDB does not provide a notification channel.
32
+ * For real-time notifications with MongoDB, use a separate notification
33
+ * channel like Redis pub/sub.
34
+ */
35
+ readonly notificationChannel: NotificationChannel | undefined;
36
+ constructor(config: MongoBackendConfig);
37
+ get repository(): JobRepository;
38
+ /**
39
+ * The job logger for persistent event logging.
40
+ * Always available; Agenda decides whether to activate it via its `logging` config.
41
+ */
42
+ get logger(): JobLogger;
43
+ /**
44
+ * Whether this backend owns its database connection.
45
+ * True if created from address (connection string), false if mongo Db was passed in.
46
+ */
47
+ get ownsConnection(): boolean;
48
+ /**
49
+ * Connect to MongoDB and initialize the collection.
50
+ */
51
+ connect(): Promise<void>;
52
+ /**
53
+ * Disconnect from MongoDB.
54
+ * Only closes the connection if we created it (i.e., from connection string).
55
+ * If an existing Db instance was passed in, this is a no-op.
56
+ */
57
+ disconnect(): Promise<void>;
58
+ }
@@ -0,0 +1,82 @@
1
+ import { MongoJobRepository } from './MongoJobRepository.js';
2
+ import { MongoJobLogger } from './MongoJobLogger.js';
3
+ /**
4
+ * MongoDB backend for Agenda.
5
+ * Provides storage via MongoDB. Does not provide notifications (uses polling).
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { Agenda } from '@quave/agenda';
10
+ * import { MongoBackend } from '@quave/agenda-mongodb';
11
+ *
12
+ * // Via connection string
13
+ * const backend = new MongoBackend({ address: 'mongodb://localhost/agenda' });
14
+ *
15
+ * // Via existing connection
16
+ * const backend = new MongoBackend({ mongo: existingDb });
17
+ *
18
+ * // With persistent job event logging
19
+ * const backend = new MongoBackend({ mongo: existingDb, logging: true });
20
+ *
21
+ * const agenda = new Agenda({ backend, logging: true });
22
+ * ```
23
+ */
24
+ export class MongoBackend {
25
+ constructor(config) {
26
+ this.config = config;
27
+ this.name = 'MongoDB';
28
+ /**
29
+ * MongoDB does not provide a notification channel.
30
+ * For real-time notifications with MongoDB, use a separate notification
31
+ * channel like Redis pub/sub.
32
+ */
33
+ this.notificationChannel = undefined;
34
+ // Determine if we own the connection (not passed in by user)
35
+ this._ownsConnection = !('mongo' in config);
36
+ this._repository = new MongoJobRepository({
37
+ ...('mongo' in config
38
+ ? { mongo: config.mongo, db: { collection: config.collection } }
39
+ : {
40
+ db: { address: config.address, collection: config.collection, options: config.options }
41
+ }),
42
+ ensureIndex: config.ensureIndex,
43
+ sort: config.sort
44
+ });
45
+ // Always create the logger (lightweight; only initializes on first use when Agenda activates it)
46
+ this._logger = new MongoJobLogger(config.logCollection);
47
+ }
48
+ get repository() {
49
+ return this._repository;
50
+ }
51
+ /**
52
+ * The job logger for persistent event logging.
53
+ * Always available; Agenda decides whether to activate it via its `logging` config.
54
+ */
55
+ get logger() {
56
+ return this._logger;
57
+ }
58
+ /**
59
+ * Whether this backend owns its database connection.
60
+ * True if created from address (connection string), false if mongo Db was passed in.
61
+ */
62
+ get ownsConnection() {
63
+ return this._ownsConnection;
64
+ }
65
+ /**
66
+ * Connect to MongoDB and initialize the collection.
67
+ */
68
+ async connect() {
69
+ await this._repository.connect();
70
+ // Initialize the job logger with the shared database connection
71
+ await this._logger.setDb(this._repository.getDb());
72
+ }
73
+ /**
74
+ * Disconnect from MongoDB.
75
+ * Only closes the connection if we created it (i.e., from connection string).
76
+ * If an existing Db instance was passed in, this is a no-op.
77
+ */
78
+ async disconnect() {
79
+ await this._repository.disconnect();
80
+ }
81
+ }
82
+ //# sourceMappingURL=MongoBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MongoBackend.js","sourceRoot":"","sources":["../src/MongoBackend.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,YAAY;IAcxB,YAAoB,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;QAbrC,SAAI,GAAG,SAAS,CAAC;QAM1B;;;;WAIG;QACM,wBAAmB,GAAoC,SAAS,CAAC;QAGzE,6DAA6D;QAC7D,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,WAAW,GAAG,IAAI,kBAAkB,CAAC;YACzC,GAAG,CAAC,OAAO,IAAI,MAAM;gBACpB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE;gBAChE,CAAC,CAAC;oBACA,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE;iBACvF,CAAC;YACJ,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;SACjB,CAAC,CAAC;QAEH,iGAAiG;QACjG,IAAI,CAAC,OAAO,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,IAAI,MAAM;QACT,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,IAAI,cAAc;QACjB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACZ,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAEjC,gEAAgE;QAChE,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU;QACf,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC;CACD"}
@@ -0,0 +1,96 @@
1
+ import type { Db, ResumeToken } from 'mongodb';
2
+ import type { JobNotification, NotificationChannelConfig } from '@quave/agenda';
3
+ import { BaseNotificationChannel } from '@quave/agenda';
4
+ /**
5
+ * Configuration for MongoChangeStreamNotificationChannel
6
+ */
7
+ export interface MongoChangeStreamNotificationChannelConfig extends NotificationChannelConfig {
8
+ /**
9
+ * MongoDB database instance.
10
+ * Required - must be connected to a replica set.
11
+ */
12
+ db?: Db;
13
+ /**
14
+ * Collection name to watch (default: 'agendaJobs')
15
+ */
16
+ collection?: string;
17
+ /**
18
+ * Resume token to resume watching from a specific point.
19
+ * Useful for recovering from disconnections.
20
+ */
21
+ resumeToken?: ResumeToken;
22
+ /**
23
+ * Whether to use fullDocument: 'updateLookup' for update events.
24
+ * This fetches the full document on updates but adds latency.
25
+ * Default: true (required for proper notification data)
26
+ */
27
+ fullDocument?: boolean;
28
+ }
29
+ /**
30
+ * MongoDB Change Stream notification channel.
31
+ *
32
+ * Uses MongoDB Change Streams to watch for job changes in real-time.
33
+ * This eliminates the need for polling and provides instant notifications
34
+ * when jobs are created or updated.
35
+ *
36
+ * **Requirements:**
37
+ * - MongoDB must be deployed as a replica set (even single-node replica sets work)
38
+ * - WiredTiger storage engine (default since MongoDB 3.2)
39
+ *
40
+ * **How it works:**
41
+ * - Watches the jobs collection for insert/update/replace operations
42
+ * - When a job with `nextRunAt` is modified, handlers are notified
43
+ * - The `publish()` method is a no-op since Change Streams automatically
44
+ * detect job changes from any source
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * import { Agenda } from '@quave/agenda';
49
+ * import { MongoBackend, MongoChangeStreamNotificationChannel } from '@quave/agenda-mongodb';
50
+ *
51
+ * const backend = new MongoBackend({ mongo: db });
52
+ * const channel = new MongoChangeStreamNotificationChannel({ db });
53
+ *
54
+ * const agenda = new Agenda({
55
+ * backend,
56
+ * notificationChannel: channel
57
+ * });
58
+ * ```
59
+ */
60
+ export declare class MongoChangeStreamNotificationChannel extends BaseNotificationChannel {
61
+ private db?;
62
+ private collectionName;
63
+ private collection?;
64
+ private changeStream?;
65
+ private resumeToken?;
66
+ private useFullDocument;
67
+ constructor(config?: MongoChangeStreamNotificationChannelConfig);
68
+ /**
69
+ * Set the MongoDB database instance.
70
+ * Used when the channel is created before the database connection.
71
+ */
72
+ setDb(db: Db): void;
73
+ /**
74
+ * Get the last resume token for reconnection purposes.
75
+ * Store this token to resume watching from the same point after restart.
76
+ */
77
+ getResumeToken(): ResumeToken | undefined;
78
+ connect(): Promise<void>;
79
+ private handleChange;
80
+ private extractFullDocument;
81
+ private buildNotification;
82
+ private handleConnectionLoss;
83
+ disconnect(): Promise<void>;
84
+ /**
85
+ * Publish a job notification.
86
+ *
87
+ * **Note:** This method is a no-op for Change Stream notifications.
88
+ * Change Streams automatically detect job changes in the database,
89
+ * so explicit publishing is not required. This method exists only
90
+ * to satisfy the NotificationChannel interface.
91
+ *
92
+ * All job saves to the watched collection will automatically trigger
93
+ * notifications to all subscribers.
94
+ */
95
+ publish(_notification: JobNotification): Promise<void>;
96
+ }