@blokjs/trigger-worker 0.2.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.
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ /**
3
+ * BullMQAdapter - Worker adapter using BullMQ (Redis-backed)
4
+ *
5
+ * Features:
6
+ * - Redis-backed persistent job queues
7
+ * - Configurable concurrency per queue
8
+ * - Job priority support
9
+ * - Delayed job scheduling
10
+ * - Automatic retries with configurable backoff
11
+ * - Queue statistics
12
+ *
13
+ * Requires: bullmq and ioredis as peer dependencies
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const adapter = new BullMQAdapter({
18
+ * host: "localhost",
19
+ * port: 6379,
20
+ * });
21
+ * ```
22
+ */
23
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ var desc = Object.getOwnPropertyDescriptor(m, k);
26
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
+ desc = { enumerable: true, get: function() { return m[k]; } };
28
+ }
29
+ Object.defineProperty(o, k2, desc);
30
+ }) : (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ o[k2] = m[k];
33
+ }));
34
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
35
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
36
+ }) : function(o, v) {
37
+ o["default"] = v;
38
+ });
39
+ var __importStar = (this && this.__importStar) || (function () {
40
+ var ownKeys = function(o) {
41
+ ownKeys = Object.getOwnPropertyNames || function (o) {
42
+ var ar = [];
43
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
44
+ return ar;
45
+ };
46
+ return ownKeys(o);
47
+ };
48
+ return function (mod) {
49
+ if (mod && mod.__esModule) return mod;
50
+ var result = {};
51
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
52
+ __setModuleDefault(result, mod);
53
+ return result;
54
+ };
55
+ })();
56
+ Object.defineProperty(exports, "__esModule", { value: true });
57
+ exports.BullMQAdapter = void 0;
58
+ /**
59
+ * BullMQ Worker Adapter
60
+ *
61
+ * Uses BullMQ for robust, Redis-backed job processing with support for
62
+ * priority queues, delayed jobs, retries, and dead letter handling.
63
+ */
64
+ class BullMQAdapter {
65
+ provider = "bullmq";
66
+ connection = null;
67
+ workers = new Map();
68
+ queues = new Map();
69
+ connected = false;
70
+ config;
71
+ constructor(config) {
72
+ this.config = {
73
+ host: config?.host || process.env.REDIS_HOST || "localhost",
74
+ port: config?.port ?? Number.parseInt(process.env.REDIS_PORT || "6379", 10),
75
+ password: config?.password || process.env.REDIS_PASSWORD,
76
+ db: config?.db ?? Number.parseInt(process.env.REDIS_DB || "0", 10),
77
+ prefix: config?.prefix || "blok-worker",
78
+ maxStalledCount: config?.maxStalledCount ?? 2,
79
+ stalledInterval: config?.stalledInterval ?? 5000,
80
+ };
81
+ }
82
+ async connect() {
83
+ if (this.connected)
84
+ return;
85
+ try {
86
+ const { default: IORedis } = await Promise.resolve().then(() => __importStar(require("ioredis")));
87
+ this.connection = new IORedis({
88
+ host: this.config.host,
89
+ port: this.config.port,
90
+ password: this.config.password,
91
+ db: this.config.db,
92
+ maxRetriesPerRequest: null, // Required for BullMQ
93
+ });
94
+ // Verify connection
95
+ await this.connection.ping();
96
+ this.connected = true;
97
+ console.log(`[BullMQAdapter] Connected to Redis at ${this.config.host}:${this.config.port}`);
98
+ }
99
+ catch (error) {
100
+ throw new Error(`Failed to connect to Redis: ${error.message}. Ensure ioredis and bullmq are installed: npm install ioredis bullmq`);
101
+ }
102
+ }
103
+ async disconnect() {
104
+ if (!this.connected)
105
+ return;
106
+ try {
107
+ // Close all workers
108
+ for (const [, worker] of this.workers) {
109
+ await worker.close();
110
+ }
111
+ this.workers.clear();
112
+ // Close all queues
113
+ for (const [, queue] of this.queues) {
114
+ await queue.close();
115
+ }
116
+ this.queues.clear();
117
+ // Close Redis connection
118
+ if (this.connection) {
119
+ await this.connection.quit();
120
+ }
121
+ this.connected = false;
122
+ console.log("[BullMQAdapter] Disconnected from Redis");
123
+ }
124
+ catch (error) {
125
+ console.error(`[BullMQAdapter] Disconnect error: ${error.message}`);
126
+ }
127
+ }
128
+ async process(config, handler) {
129
+ if (!this.connected) {
130
+ throw new Error("Not connected. Call connect() first.");
131
+ }
132
+ try {
133
+ // Dynamic import to avoid hard dependency on bullmq
134
+ const bullmq = await Promise.resolve().then(() => __importStar(require("bullmq")));
135
+ const BullWorker = bullmq.Worker;
136
+ const BullQueue = bullmq.Queue;
137
+ // Build worker options
138
+ const workerOpts = {
139
+ connection: this.connection,
140
+ concurrency: config.concurrency ?? 1,
141
+ prefix: this.config.prefix,
142
+ stalledInterval: this.config.stalledInterval ?? 5000,
143
+ maxStalledCount: this.config.maxStalledCount ?? 2,
144
+ };
145
+ const worker = new BullWorker(config.queue,
146
+ // BullMQ processor callback
147
+ ((bullJob) => {
148
+ const job = bullJob;
149
+ const workerJob = {
150
+ id: job.id || `job-${Date.now()}`,
151
+ data: job.data,
152
+ headers: job.data?._headers || {},
153
+ queue: config.queue,
154
+ priority: job.opts?.priority ?? config.priority ?? 0,
155
+ attempts: job.attemptsMade,
156
+ maxRetries: config.retries ?? 3,
157
+ createdAt: new Date(job.timestamp),
158
+ delay: job.opts?.delay,
159
+ timeout: config.timeout,
160
+ raw: job,
161
+ complete: async () => {
162
+ // BullMQ auto-completes when processor resolves
163
+ },
164
+ fail: async (error, requeue) => {
165
+ if (!requeue) {
166
+ await job.moveToFailed(error, job.token || "", true);
167
+ }
168
+ else {
169
+ throw error; // BullMQ will auto-retry
170
+ }
171
+ },
172
+ };
173
+ return handler(workerJob);
174
+ }), workerOpts);
175
+ this.workers.set(config.queue, worker);
176
+ // Ensure queue object exists for job dispatching
177
+ if (!this.queues.has(config.queue)) {
178
+ const queue = new BullQueue(config.queue, {
179
+ connection: this.connection,
180
+ prefix: this.config.prefix,
181
+ });
182
+ this.queues.set(config.queue, queue);
183
+ }
184
+ console.log(`[BullMQAdapter] Processing queue: ${config.queue} (concurrency=${config.concurrency ?? 1})`);
185
+ }
186
+ catch (error) {
187
+ throw new Error(`Failed to start processing: ${error.message}`);
188
+ }
189
+ }
190
+ async addJob(queue, data, opts) {
191
+ if (!this.connected) {
192
+ throw new Error("Not connected. Call connect() first.");
193
+ }
194
+ try {
195
+ // Ensure queue exists
196
+ if (!this.queues.has(queue)) {
197
+ const { Queue } = await Promise.resolve().then(() => __importStar(require("bullmq")));
198
+ const q = new Queue(queue, {
199
+ connection: this.connection,
200
+ prefix: this.config.prefix,
201
+ });
202
+ this.queues.set(queue, q);
203
+ }
204
+ const q = this.queues.get(queue);
205
+ const job = await q.add("process", data, {
206
+ priority: opts?.priority,
207
+ delay: opts?.delay,
208
+ attempts: (opts?.retries ?? 3) + 1,
209
+ jobId: opts?.jobId,
210
+ backoff: {
211
+ type: "exponential",
212
+ delay: 1000,
213
+ },
214
+ });
215
+ return job.id;
216
+ }
217
+ catch (error) {
218
+ throw new Error(`Failed to add job: ${error.message}`);
219
+ }
220
+ }
221
+ async stopProcessing(queue) {
222
+ const worker = this.workers.get(queue);
223
+ if (worker) {
224
+ await worker.close();
225
+ this.workers.delete(queue);
226
+ console.log(`[BullMQAdapter] Stopped processing queue: ${queue}`);
227
+ }
228
+ }
229
+ isConnected() {
230
+ return this.connected;
231
+ }
232
+ async healthCheck() {
233
+ if (!this.connected || !this.connection)
234
+ return false;
235
+ try {
236
+ await this.connection.ping();
237
+ return true;
238
+ }
239
+ catch {
240
+ return false;
241
+ }
242
+ }
243
+ async getQueueStats(queue) {
244
+ if (!this.queues.has(queue)) {
245
+ return { waiting: 0, active: 0, completed: 0, failed: 0, delayed: 0 };
246
+ }
247
+ const q = this.queues.get(queue);
248
+ const [waiting, active, completed, failed, delayed] = await Promise.all([
249
+ q.getWaitingCount(),
250
+ q.getActiveCount(),
251
+ q.getCompletedCount(),
252
+ q.getFailedCount(),
253
+ q.getDelayedCount(),
254
+ ]);
255
+ return { waiting, active, completed, failed, delayed };
256
+ }
257
+ }
258
+ exports.BullMQAdapter = BullMQAdapter;
259
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQnVsbE1RQWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVycy9CdWxsTVFBZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTBCSDs7Ozs7R0FLRztBQUNILE1BQWEsYUFBYTtJQUNoQixRQUFRLEdBQUcsUUFBaUIsQ0FBQztJQUM5QixVQUFVLEdBQVksSUFBSSxDQUFDO0lBQzNCLE9BQU8sR0FBeUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMxQyxNQUFNLEdBQXlCLElBQUksR0FBRyxFQUFFLENBQUM7SUFDekMsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNULE1BQU0sQ0FBZTtJQUV0QyxZQUFZLE1BQThCO1FBQ3pDLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDYixJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxXQUFXO1lBQzNELElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUMzRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWM7WUFDeEQsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsSUFBSSxHQUFHLEVBQUUsRUFBRSxDQUFDO1lBQ2xFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxJQUFJLGFBQWE7WUFDdkMsZUFBZSxFQUFFLE1BQU0sRUFBRSxlQUFlLElBQUksQ0FBQztZQUM3QyxlQUFlLEVBQUUsTUFBTSxFQUFFLGVBQWUsSUFBSSxJQUFJ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LEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUN2RSxDQUFDO1FBRUQsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQU05QixDQUFDO1FBRUYsTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDdkUsQ0FBQyxDQUFDLGVBQWUsRUFBRTtZQUNuQixDQUFDLENBQUMsY0FBYyxFQUFFO1lBQ2xCLENBQUMsQ0FBQyxpQkFBaUIsRUFBRTtZQUNyQixDQUFDLENBQUMsY0FBYyxFQUFFO1lBQ2xCLENBQUMsQ0FBQyxlQUFlLEVBQUU7U0FDbkIsQ0FBQyxDQUFDO1FBRUgsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUN4RCxDQUFDO0NBQ0Q7QUFuUEQsc0NBbVBDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCdWxsTVFBZGFwdGVyIC0gV29ya2VyIGFkYXB0ZXIgdXNpbmcgQnVsbE1RIChSZWRpcy1iYWNrZWQpXG4gKlxuICogRmVhdHVyZXM6XG4gKiAtIFJlZGlzLWJhY2tlZCBwZXJzaXN0ZW50IGpvYiBxdWV1ZXNcbiAqIC0gQ29uZmlndXJhYmxlIGNvbmN1cnJlbmN5IHBlciBxdWV1ZVxuICogLSBKb2IgcHJpb3JpdHkgc3VwcG9ydFxuICogLSBEZWxheWVkIGpvYiBzY2hlZHVsaW5nXG4gKiAtIEF1dG9tYXRpYyByZXRyaWVzIHdpdGggY29uZmlndXJhYmxlIGJhY2tvZmZcbiAqIC0gUXVldWUgc3RhdGlzdGljc1xuICpcbiAqIFJlcXVpcmVzOiBidWxsbXEgYW5kIGlvcmVkaXMgYXMgcGVlciBkZXBlbmRlbmNpZXNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgYWRhcHRlciA9IG5ldyBCdWxsTVFBZGFwdGVyKHtcbiAqICAgaG9zdDogXCJsb2NhbGhvc3RcIixcbiAqICAgcG9ydDogNjM3OSxcbiAqIH0pO1xuICogYGBgXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBXb3JrZXJBZGFwdGVyLCBXb3JrZXJKb2IsIFdvcmtlclF1ZXVlU3RhdHMgfSBmcm9tIFwiLi4vV29ya2VyVHJpZ2dlclwiO1xuXG5pbXBvcnQgdHlwZSB7IFdvcmtlclRyaWdnZXJPcHRzIH0gZnJvbSBcIkBibG9rL2hlbHBlclwiO1xuXG4vKipcbiAqIEJ1bGxNUSBhZGFwdGVyIGNvbmZpZ3VyYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWxsTVFDb25maWcge1xuXHQvKiogUmVkaXMgaG9zdCAoZGVmYXVsdDogZnJvbSBSRURJU19IT1NUIGVudiBvciBcImxvY2FsaG9zdFwiKSAqL1xuXHRob3N0OiBzdHJpbmc7XG5cdC8qKiBSZWRpcyBwb3J0IChkZWZhdWx0OiBmcm9tIFJFRElTX1BPUlQgZW52IG9yIDYzNzkpICovXG5cdHBvcnQ6IG51bWJlcjtcblx0LyoqIFJlZGlzIHBhc3N3b3JkIChkZWZhdWx0OiBmcm9tIFJFRElTX1BBU1NXT1JEIGVudikgKi9cblx0cGFzc3dvcmQ/OiBzdHJpbmc7XG5cdC8qKiBSZWRpcyBkYXRhYmFzZSAoZGVmYXVsdDogZnJvbSBSRURJU19EQiBlbnYgb3IgMCkgKi9cblx0ZGI/OiBudW1iZXI7XG5cdC8qKiBLZXkgcHJlZml4IGZvciBhbGwgQnVsbE1RIGtleXMgKi9cblx0cHJlZml4Pzogc3RyaW5nO1xuXHQvKiogTWF4IHN0YWxsZWQgY291bnQgYmVmb3JlIGpvYiBmYWlscyAqL1xuXHRtYXhTdGFsbGVkQ291bnQ/OiBudW1iZXI7XG5cdC8qKiBTdGFsbGVkIGludGVydmFsIGluIG1zICovXG5cdHN0YWxsZWRJbnRlcnZhbD86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBCdWxsTVEgV29ya2VyIEFkYXB0ZXJcbiAqXG4gKiBVc2VzIEJ1bGxNUSBmb3Igcm9idXN0LCBSZWRpcy1iYWNrZWQgam9iIHByb2Nlc3Npbmcgd2l0aCBzdXBwb3J0IGZvclxuICogcHJpb3JpdHkgcXVldWVzLCBkZWxheWVkIGpvYnMsIHJldHJpZXMsIGFuZCBkZWFkIGxldHRlciBoYW5kbGluZy5cbiAqL1xuZXhwb3J0IGNsYXNzIEJ1bGxNUUFkYXB0ZXIgaW1wbGVtZW50cyBXb3JrZXJBZGFwdGVyIHtcblx0cmVhZG9ubHkgcHJvdmlkZXIgPSBcImJ1bGxtcVwiIGFzIGNvbnN0O1xuXHRwcml2YXRlIGNvbm5lY3Rpb246IHVua25vd24gPSBudWxsO1xuXHRwcml2YXRlIHdvcmtlcnM6IE1hcDxzdHJpbmcsIHVua25vd24+ID0gbmV3IE1hcCgpO1xuXHRwcml2YXRlIHF1ZXVlczogTWFwPHN0cmluZywgdW5rbm93bj4gPSBuZXcgTWFwKCk7XG5cdHByaXZhdGUgY29ubmVjdGVkID0gZmFsc2U7XG5cdHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBCdWxsTVFDb25maWc7XG5cblx0Y29uc3RydWN0b3IoY29uZmlnPzogUGFydGlhbDxCdWxsTVFDb25maWc+KSB7XG5cdFx0dGhpcy5jb25maWcgPSB7XG5cdFx0XHRob3N0OiBjb25maWc/Lmhvc3QgfHwgcHJvY2Vzcy5lbnYuUkVESVNfSE9TVCB8fCBcImxvY2FsaG9zdFwiLFxuXHRcdFx0cG9ydDogY29uZmlnPy5wb3J0ID8/IE51bWJlci5wYXJzZUludChwcm9jZXNzLmVudi5SRURJU19QT1JUIHx8IFwiNjM3OVwiLCAxMCksXG5cdFx0XHRwYXNzd29yZDogY29uZmlnPy5wYXNzd29yZCB8fCBwcm9jZXNzLmVudi5SRURJU19QQVNTV09SRCxcblx0XHRcdGRiOiBjb25maWc/LmRiID8/IE51bWJlci5wYXJzZUludChwcm9jZXNzLmVudi5SRURJU19EQiB8fCBcIjBcIiwgMTApLFxuXHRcdFx0cHJlZml4OiBjb25maWc/LnByZWZpeCB8fCBcImJsb2std29ya2VyXCIsXG5cdFx0XHRtYXhTdGFsbGVkQ291bnQ6IGNvbmZpZz8ubWF4U3RhbGxlZENvdW50ID8/IDIsXG5cdFx0XHRzdGFsbGVkSW50ZXJ2YWw6IGNvbmZpZz8uc3RhbGxlZEludGVydmFsID8/IDUwMDAsXG5cdFx0fTtcblx0fVxuXG5cdGFzeW5jIGNvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKHRoaXMuY29ubmVjdGVkKSByZXR1cm47XG5cblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgeyBkZWZhdWx0OiBJT1JlZGlzIH0gPSBhd2FpdCBpbXBvcnQoXCJpb3JlZGlzXCIpO1xuXHRcdFx0dGhpcy5jb25uZWN0aW9uID0gbmV3IElPUmVkaXMoe1xuXHRcdFx0XHRob3N0OiB0aGlzLmNvbmZpZy5ob3N0LFxuXHRcdFx0XHRwb3J0OiB0aGlzLmNvbmZpZy5wb3J0LFxuXHRcdFx0XHRwYXNzd29yZDogdGhpcy5jb25maWcucGFzc3dvcmQsXG5cdFx0XHRcdGRiOiB0aGlzLmNvbmZpZy5kYixcblx0XHRcdFx0bWF4UmV0cmllc1BlclJlcXVlc3Q6IG51bGwsIC8vIFJlcXVpcmVkIGZvciBCdWxsTVFcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBWZXJpZnkgY29ubmVjdGlvblxuXHRcdFx0YXdhaXQgKHRoaXMuY29ubmVjdGlvbiBhcyB7IHBpbmc6ICgpID0+IFByb21pc2U8c3RyaW5nPiB9KS5waW5nKCk7XG5cdFx0XHR0aGlzLmNvbm5lY3RlZCA9IHRydWU7XG5cdFx0XHRjb25zb2xlLmxvZyhgW0J1bGxNUUFkYXB0ZXJdIENvbm5lY3RlZCB0byBSZWRpcyBhdCAke3RoaXMuY29uZmlnLmhvc3R9OiR7dGhpcy5jb25maWcucG9ydH1gKTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFxuXHRcdFx0XHRgRmFpbGVkIHRvIGNvbm5lY3QgdG8gUmVkaXM6ICR7KGVycm9yIGFzIEVycm9yKS5tZXNzYWdlfS4gRW5zdXJlIGlvcmVkaXMgYW5kIGJ1bGxtcSBhcmUgaW5zdGFsbGVkOiBucG0gaW5zdGFsbCBpb3JlZGlzIGJ1bGxtcWAsXG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIGRpc2Nvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKCF0aGlzLmNvbm5lY3RlZCkgcmV0dXJuO1xuXG5cdFx0dHJ5IHtcblx0XHRcdC8vIENsb3NlIGFsbCB3b3JrZXJzXG5cdFx0XHRmb3IgKGNvbnN0IFssIHdvcmtlcl0gb2YgdGhpcy53b3JrZXJzKSB7XG5cdFx0XHRcdGF3YWl0ICh3b3JrZXIgYXMgeyBjbG9zZTogKCkgPT4gUHJvbWlzZTx2b2lkPiB9KS5jbG9zZSgpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy53b3JrZXJzLmNsZWFyKCk7XG5cblx0XHRcdC8vIENsb3NlIGFsbCBxdWV1ZXNcblx0XHRcdGZvciAoY29uc3QgWywgcXVldWVdIG9mIHRoaXMucXVldWVzKSB7XG5cdFx0XHRcdGF3YWl0IChxdWV1ZSBhcyB7IGNsb3NlOiAoKSA9PiBQcm9taXNlPHZvaWQ+IH0pLmNsb3NlKCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnF1ZXVlcy5jbGVhcigpO1xuXG5cdFx0XHQvLyBDbG9zZSBSZWRpcyBjb25uZWN0aW9uXG5cdFx0XHRpZiAodGhpcy5jb25uZWN0aW9uKSB7XG5cdFx0XHRcdGF3YWl0ICh0aGlzLmNvbm5lY3Rpb24gYXMgeyBxdWl0OiAoKSA9PiBQcm9taXNlPHN0cmluZz4gfSkucXVpdCgpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuXHRcdFx0Y29uc29sZS5sb2coXCJbQnVsbE1RQWRhcHRlcl0gRGlzY29ubmVjdGVkIGZyb20gUmVkaXNcIik7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoYFtCdWxsTVFBZGFwdGVyXSBEaXNjb25uZWN0IGVycm9yOiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcblx0XHR9XG5cdH1cblxuXHRhc3luYyBwcm9jZXNzKGNvbmZpZzogV29ya2VyVHJpZ2dlck9wdHMsIGhhbmRsZXI6IChqb2I6IFdvcmtlckpvYikgPT4gUHJvbWlzZTx2b2lkPik6IFByb21pc2U8dm9pZD4ge1xuXHRcdGlmICghdGhpcy5jb25uZWN0ZWQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIk5vdCBjb25uZWN0ZWQuIENhbGwgY29ubmVjdCgpIGZpcnN0LlwiKTtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0Ly8gRHluYW1pYyBpbXBvcnQgdG8gYXZvaWQgaGFyZCBkZXBlbmRlbmN5IG9uIGJ1bGxtcVxuXHRcdFx0Y29uc3QgYnVsbG1xID0gYXdhaXQgaW1wb3J0KFwiYnVsbG1xXCIpO1xuXHRcdFx0Y29uc3QgQnVsbFdvcmtlciA9IGJ1bGxtcS5Xb3JrZXI7XG5cdFx0XHRjb25zdCBCdWxsUXVldWUgPSBidWxsbXEuUXVldWU7XG5cblx0XHRcdC8vIEJ1aWxkIHdvcmtlciBvcHRpb25zXG5cdFx0XHRjb25zdCB3b3JrZXJPcHRzID0ge1xuXHRcdFx0XHRjb25uZWN0aW9uOiB0aGlzLmNvbm5lY3Rpb24sXG5cdFx0XHRcdGNvbmN1cnJlbmN5OiBjb25maWcuY29uY3VycmVuY3kgPz8gMSxcblx0XHRcdFx0cHJlZml4OiB0aGlzLmNvbmZpZy5wcmVmaXgsXG5cdFx0XHRcdHN0YWxsZWRJbnRlcnZhbDogdGhpcy5jb25maWcuc3RhbGxlZEludGVydmFsID8/IDUwMDAsXG5cdFx0XHRcdG1heFN0YWxsZWRDb3VudDogdGhpcy5jb25maWcubWF4U3RhbGxlZENvdW50ID8/IDIsXG5cdFx0XHR9O1xuXG5cdFx0XHRjb25zdCB3b3JrZXIgPSBuZXcgQnVsbFdvcmtlcihcblx0XHRcdFx0Y29uZmlnLnF1ZXVlLFxuXHRcdFx0XHQvLyBCdWxsTVEgcHJvY2Vzc29yIGNhbGxiYWNrXG5cdFx0XHRcdCgoYnVsbEpvYjogdW5rbm93bikgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IGpvYiA9IGJ1bGxKb2IgYXMge1xuXHRcdFx0XHRcdFx0aWQ/OiBzdHJpbmc7XG5cdFx0XHRcdFx0XHRkYXRhOiB1bmtub3duO1xuXHRcdFx0XHRcdFx0b3B0cz86IHsgcHJpb3JpdHk/OiBudW1iZXI7IGRlbGF5PzogbnVtYmVyIH07XG5cdFx0XHRcdFx0XHRhdHRlbXB0c01hZGU6IG51bWJlcjtcblx0XHRcdFx0XHRcdHRpbWVzdGFtcDogbnVtYmVyO1xuXHRcdFx0XHRcdFx0dG9rZW4/OiBzdHJpbmc7XG5cdFx0XHRcdFx0XHRtb3ZlVG9GYWlsZWQ6IChlcnI6IEVycm9yLCB0b2tlbjogc3RyaW5nLCBmZXRjaE5leHQ6IGJvb2xlYW4pID0+IFByb21pc2U8dm9pZD47XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRjb25zdCB3b3JrZXJKb2I6IFdvcmtlckpvYiA9IHtcblx0XHRcdFx0XHRcdGlkOiBqb2IuaWQgfHwgYGpvYi0ke0RhdGUubm93KCl9YCxcblx0XHRcdFx0XHRcdGRhdGE6IGpvYi5kYXRhLFxuXHRcdFx0XHRcdFx0aGVhZGVyczogKChqb2IuZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik/Ll9oZWFkZXJzIGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4pIHx8IHt9LFxuXHRcdFx0XHRcdFx0cXVldWU6IGNvbmZpZy5xdWV1ZSxcblx0XHRcdFx0XHRcdHByaW9yaXR5OiBqb2Iub3B0cz8ucHJpb3JpdHkgPz8gY29uZmlnLnByaW9yaXR5ID8/IDAsXG5cdFx0XHRcdFx0XHRhdHRlbXB0czogam9iLmF0dGVtcHRzTWFkZSxcblx0XHRcdFx0XHRcdG1heFJldHJpZXM6IGNvbmZpZy5yZXRyaWVzID8/IDMsXG5cdFx0XHRcdFx0XHRjcmVhdGVkQXQ6IG5ldyBEYXRlKGpvYi50aW1lc3RhbXApLFxuXHRcdFx0XHRcdFx0ZGVsYXk6IGpvYi5vcHRzPy5kZWxheSxcblx0XHRcdFx0XHRcdHRpbWVvdXQ6IGNvbmZpZy50aW1lb3V0LFxuXHRcdFx0XHRcdFx0cmF3OiBqb2IsXG5cdFx0XHRcdFx0XHRjb21wbGV0ZTogYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHQvLyBCdWxsTVEgYXV0by1jb21wbGV0ZXMgd2hlbiBwcm9jZXNzb3IgcmVzb2x2ZXNcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRmYWlsOiBhc3luYyAoZXJyb3I6IEVycm9yLCByZXF1ZXVlPzogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRpZiAoIXJlcXVldWUpIHtcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCBqb2IubW92ZVRvRmFpbGVkKGVycm9yLCBqb2IudG9rZW4gfHwgXCJcIiwgdHJ1ZSk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhyb3cgZXJyb3I7IC8vIEJ1bGxNUSB3aWxsIGF1dG8tcmV0cnlcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdHJldHVybiBoYW5kbGVyKHdvcmtlckpvYik7XG5cdFx0XHRcdH0pIGFzIG5ldmVyLFxuXHRcdFx0XHR3b3JrZXJPcHRzIGFzIG5ldmVyLFxuXHRcdFx0KTtcblxuXHRcdFx0dGhpcy53b3JrZXJzLnNldChjb25maWcucXVldWUsIHdvcmtlcik7XG5cblx0XHRcdC8vIEVuc3VyZSBxdWV1ZSBvYmplY3QgZXhpc3RzIGZvciBqb2IgZGlzcGF0Y2hpbmdcblx0XHRcdGlmICghdGhpcy5xdWV1ZXMuaGFzKGNvbmZpZy5xdWV1ZSkpIHtcblx0XHRcdFx0Y29uc3QgcXVldWUgPSBuZXcgQnVsbFF1ZXVlKGNvbmZpZy5xdWV1ZSwge1xuXHRcdFx0XHRcdGNvbm5lY3Rpb246IHRoaXMuY29ubmVjdGlvbiBhcyB7IGhvc3Q6IHN0cmluZzsgcG9ydDogbnVtYmVyIH0sXG5cdFx0XHRcdFx0cHJlZml4OiB0aGlzLmNvbmZpZy5wcmVmaXgsXG5cdFx0XHRcdH0gYXMgbmV2ZXIpO1xuXHRcdFx0XHR0aGlzLnF1ZXVlcy5zZXQoY29uZmlnLnF1ZXVlLCBxdWV1ZSk7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnNvbGUubG9nKGBbQnVsbE1RQWRhcHRlcl0gUHJvY2Vzc2luZyBxdWV1ZTogJHtjb25maWcucXVldWV9IChjb25jdXJyZW5jeT0ke2NvbmZpZy5jb25jdXJyZW5jeSA/PyAxfSlgKTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gc3RhcnQgcHJvY2Vzc2luZzogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgYWRkSm9iKFxuXHRcdHF1ZXVlOiBzdHJpbmcsXG5cdFx0ZGF0YTogdW5rbm93bixcblx0XHRvcHRzPzoge1xuXHRcdFx0cHJpb3JpdHk/OiBudW1iZXI7XG5cdFx0XHRkZWxheT86IG51bWJlcjtcblx0XHRcdHJldHJpZXM/OiBudW1iZXI7XG5cdFx0XHR0aW1lb3V0PzogbnVtYmVyO1xuXHRcdFx0am9iSWQ/OiBzdHJpbmc7XG5cdFx0fSxcblx0KTogUHJvbWlzZTxzdHJpbmc+IHtcblx0XHRpZiAoIXRoaXMuY29ubmVjdGVkKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJOb3QgY29ubmVjdGVkLiBDYWxsIGNvbm5lY3QoKSBmaXJzdC5cIik7XG5cdFx0fVxuXG5cdFx0dHJ5IHtcblx0XHRcdC8vIEVuc3VyZSBxdWV1ZSBleGlzdHNcblx0XHRcdGlmICghdGhpcy5xdWV1ZXMuaGFzKHF1ZXVlKSkge1xuXHRcdFx0XHRjb25zdCB7IFF1ZXVlIH0gPSBhd2FpdCBpbXBvcnQoXCJidWxsbXFcIik7XG5cdFx0XHRcdGNvbnN0IHEgPSBuZXcgUXVldWUocXVldWUsIHtcblx0XHRcdFx0XHRjb25uZWN0aW9uOiB0aGlzLmNvbm5lY3Rpb24gYXMgeyBob3N0OiBzdHJpbmc7IHBvcnQ6IG51bWJlciB9LFxuXHRcdFx0XHRcdHByZWZpeDogdGhpcy5jb25maWcucHJlZml4LFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0dGhpcy5xdWV1ZXMuc2V0KHF1ZXVlLCBxKTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgcSA9IHRoaXMucXVldWVzLmdldChxdWV1ZSkgYXMge1xuXHRcdFx0XHRhZGQ6IChuYW1lOiBzdHJpbmcsIGRhdGE6IHVua25vd24sIG9wdHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBQcm9taXNlPHsgaWQ6IHN0cmluZyB9Pjtcblx0XHRcdH07XG5cblx0XHRcdGNvbnN0IGpvYiA9IGF3YWl0IHEuYWRkKFwicHJvY2Vzc1wiLCBkYXRhLCB7XG5cdFx0XHRcdHByaW9yaXR5OiBvcHRzPy5wcmlvcml0eSxcblx0XHRcdFx0ZGVsYXk6IG9wdHM/LmRlbGF5LFxuXHRcdFx0XHRhdHRlbXB0czogKG9wdHM/LnJldHJpZXMgPz8gMykgKyAxLFxuXHRcdFx0XHRqb2JJZDogb3B0cz8uam9iSWQsXG5cdFx0XHRcdGJhY2tvZmY6IHtcblx0XHRcdFx0XHR0eXBlOiBcImV4cG9uZW50aWFsXCIsXG5cdFx0XHRcdFx0ZGVsYXk6IDEwMDAsXG5cdFx0XHRcdH0sXG5cdFx0XHR9KTtcblxuXHRcdFx0cmV0dXJuIGpvYi5pZDtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gYWRkIGpvYjogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgc3RvcFByb2Nlc3NpbmcocXVldWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGNvbnN0IHdvcmtlciA9IHRoaXMud29ya2Vycy5nZXQocXVldWUpO1xuXHRcdGlmICh3b3JrZXIpIHtcblx0XHRcdGF3YWl0ICh3b3JrZXIgYXMgeyBjbG9zZTogKCkgPT4gUHJvbWlzZTx2b2lkPiB9KS5jbG9zZSgpO1xuXHRcdFx0dGhpcy53b3JrZXJzLmRlbGV0ZShxdWV1ZSk7XG5cdFx0XHRjb25zb2xlLmxvZyhgW0J1bGxNUUFkYXB0ZXJdIFN0b3BwZWQgcHJvY2Vzc2luZyBxdWV1ZTogJHtxdWV1ZX1gKTtcblx0XHR9XG5cdH1cblxuXHRpc0Nvbm5lY3RlZCgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5jb25uZWN0ZWQ7XG5cdH1cblxuXHRhc3luYyBoZWFsdGhDaGVjaygpOiBQcm9taXNlPGJvb2xlYW4+IHtcblx0XHRpZiAoIXRoaXMuY29ubmVjdGVkIHx8ICF0aGlzLmNvbm5lY3Rpb24pIHJldHVybiBmYWxzZTtcblx0XHR0cnkge1xuXHRcdFx0YXdhaXQgKHRoaXMuY29ubmVjdGlvbiBhcyB7IHBpbmc6ICgpID0+IFByb21pc2U8c3RyaW5nPiB9KS5waW5nKCk7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHRhc3luYyBnZXRRdWV1ZVN0YXRzKHF1ZXVlOiBzdHJpbmcpOiBQcm9taXNlPFdvcmtlclF1ZXVlU3RhdHM+IHtcblx0XHRpZiAoIXRoaXMucXVldWVzLmhhcyhxdWV1ZSkpIHtcblx0XHRcdHJldHVybiB7IHdhaXRpbmc6IDAsIGFjdGl2ZTogMCwgY29tcGxldGVkOiAwLCBmYWlsZWQ6IDAsIGRlbGF5ZWQ6IDAgfTtcblx0XHR9XG5cblx0XHRjb25zdCBxID0gdGhpcy5xdWV1ZXMuZ2V0KHF1ZXVlKSBhcyB7XG5cdFx0XHRnZXRXYWl0aW5nQ291bnQ6ICgpID0+IFByb21pc2U8bnVtYmVyPjtcblx0XHRcdGdldEFjdGl2ZUNvdW50OiAoKSA9PiBQcm9taXNlPG51bWJlcj47XG5cdFx0XHRnZXRDb21wbGV0ZWRDb3VudDogKCkgPT4gUHJvbWlzZTxudW1iZXI+O1xuXHRcdFx0Z2V0RmFpbGVkQ291bnQ6ICgpID0+IFByb21pc2U8bnVtYmVyPjtcblx0XHRcdGdldERlbGF5ZWRDb3VudDogKCkgPT4gUHJvbWlzZTxudW1iZXI+O1xuXHRcdH07XG5cblx0XHRjb25zdCBbd2FpdGluZywgYWN0aXZlLCBjb21wbGV0ZWQsIGZhaWxlZCwgZGVsYXllZF0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG5cdFx0XHRxLmdldFdhaXRpbmdDb3VudCgpLFxuXHRcdFx0cS5nZXRBY3RpdmVDb3VudCgpLFxuXHRcdFx0cS5nZXRDb21wbGV0ZWRDb3VudCgpLFxuXHRcdFx0cS5nZXRGYWlsZWRDb3VudCgpLFxuXHRcdFx0cS5nZXREZWxheWVkQ291bnQoKSxcblx0XHRdKTtcblxuXHRcdHJldHVybiB7IHdhaXRpbmcsIGFjdGl2ZSwgY29tcGxldGVkLCBmYWlsZWQsIGRlbGF5ZWQgfTtcblx0fVxufVxuIl19
@@ -0,0 +1,48 @@
1
+ /**
2
+ * InMemoryAdapter - Worker adapter using in-process queues
3
+ *
4
+ * Ideal for:
5
+ * - Development and testing
6
+ * - Simple background job processing
7
+ * - Single-instance deployments
8
+ *
9
+ * Limitations:
10
+ * - Jobs are lost on process restart
11
+ * - No distributed processing
12
+ * - No persistence
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const adapter = new InMemoryAdapter();
17
+ * ```
18
+ */
19
+ import type { WorkerTriggerOpts } from "@blok/helper";
20
+ import type { WorkerAdapter, WorkerJob, WorkerQueueStats } from "../WorkerTrigger";
21
+ /**
22
+ * InMemoryAdapter - Simple in-process worker queue
23
+ */
24
+ export declare class InMemoryAdapter implements WorkerAdapter {
25
+ readonly provider: "in-memory";
26
+ private connected;
27
+ private jobs;
28
+ private processors;
29
+ private stats;
30
+ connect(): Promise<void>;
31
+ disconnect(): Promise<void>;
32
+ process(config: WorkerTriggerOpts, handler: (job: WorkerJob) => Promise<void>): Promise<void>;
33
+ addJob(queue: string, data: unknown, opts?: {
34
+ priority?: number;
35
+ delay?: number;
36
+ retries?: number;
37
+ timeout?: number;
38
+ jobId?: string;
39
+ }): Promise<string>;
40
+ stopProcessing(queue: string): Promise<void>;
41
+ isConnected(): boolean;
42
+ healthCheck(): Promise<boolean>;
43
+ getQueueStats(queue: string): Promise<WorkerQueueStats>;
44
+ /**
45
+ * Process the next available job from a queue
46
+ */
47
+ private processNext;
48
+ }
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ /**
3
+ * InMemoryAdapter - Worker adapter using in-process queues
4
+ *
5
+ * Ideal for:
6
+ * - Development and testing
7
+ * - Simple background job processing
8
+ * - Single-instance deployments
9
+ *
10
+ * Limitations:
11
+ * - Jobs are lost on process restart
12
+ * - No distributed processing
13
+ * - No persistence
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const adapter = new InMemoryAdapter();
18
+ * ```
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.InMemoryAdapter = void 0;
22
+ const uuid_1 = require("uuid");
23
+ /**
24
+ * InMemoryAdapter - Simple in-process worker queue
25
+ */
26
+ class InMemoryAdapter {
27
+ provider = "in-memory";
28
+ connected = false;
29
+ jobs = new Map();
30
+ processors = new Map();
31
+ stats = new Map();
32
+ async connect() {
33
+ this.connected = true;
34
+ }
35
+ async disconnect() {
36
+ // Stop all processors
37
+ for (const [queue, processor] of this.processors) {
38
+ processor.running = false;
39
+ if (processor.timer) {
40
+ clearInterval(processor.timer);
41
+ }
42
+ }
43
+ this.processors.clear();
44
+ this.jobs.clear();
45
+ this.stats.clear();
46
+ this.connected = false;
47
+ }
48
+ async process(config, handler) {
49
+ if (!this.connected) {
50
+ throw new Error("Not connected. Call connect() first.");
51
+ }
52
+ if (!this.jobs.has(config.queue)) {
53
+ this.jobs.set(config.queue, []);
54
+ }
55
+ if (!this.stats.has(config.queue)) {
56
+ this.stats.set(config.queue, { completed: 0, failed: 0 });
57
+ }
58
+ const processor = {
59
+ config,
60
+ handler,
61
+ active: 0,
62
+ running: true,
63
+ };
64
+ this.processors.set(config.queue, processor);
65
+ // Start polling for jobs
66
+ processor.timer = setInterval(() => {
67
+ this.processNext(config.queue).catch((err) => {
68
+ console.error(`[InMemoryAdapter] Error processing ${config.queue}: ${err.message}`);
69
+ });
70
+ }, 50); // Poll every 50ms
71
+ }
72
+ async addJob(queue, data, opts) {
73
+ if (!this.connected) {
74
+ throw new Error("Not connected. Call connect() first.");
75
+ }
76
+ if (!this.jobs.has(queue)) {
77
+ this.jobs.set(queue, []);
78
+ }
79
+ if (!this.stats.has(queue)) {
80
+ this.stats.set(queue, { completed: 0, failed: 0 });
81
+ }
82
+ const job = {
83
+ id: opts?.jobId || (0, uuid_1.v4)(),
84
+ data,
85
+ queue,
86
+ priority: opts?.priority ?? 0,
87
+ attempts: 0,
88
+ maxRetries: opts?.retries ?? 3,
89
+ createdAt: new Date(),
90
+ delay: opts?.delay ?? 0,
91
+ timeout: opts?.timeout ?? 0,
92
+ status: opts?.delay && opts.delay > 0 ? "delayed" : "waiting",
93
+ };
94
+ if (job.status === "delayed") {
95
+ job.scheduledAt = new Date(Date.now() + job.delay);
96
+ }
97
+ const jobs = this.jobs.get(queue);
98
+ // Insert sorted by priority (higher first)
99
+ const insertIdx = jobs.findIndex((j) => j.status === "waiting" && j.priority < job.priority);
100
+ if (insertIdx >= 0) {
101
+ jobs.splice(insertIdx, 0, job);
102
+ }
103
+ else {
104
+ jobs.push(job);
105
+ }
106
+ return job.id;
107
+ }
108
+ async stopProcessing(queue) {
109
+ const processor = this.processors.get(queue);
110
+ if (processor) {
111
+ processor.running = false;
112
+ if (processor.timer) {
113
+ clearInterval(processor.timer);
114
+ }
115
+ this.processors.delete(queue);
116
+ }
117
+ }
118
+ isConnected() {
119
+ return this.connected;
120
+ }
121
+ async healthCheck() {
122
+ return this.connected;
123
+ }
124
+ async getQueueStats(queue) {
125
+ const jobs = this.jobs.get(queue) || [];
126
+ const queueStats = this.stats.get(queue) || { completed: 0, failed: 0 };
127
+ return {
128
+ waiting: jobs.filter((j) => j.status === "waiting").length,
129
+ active: jobs.filter((j) => j.status === "active").length,
130
+ completed: queueStats.completed,
131
+ failed: queueStats.failed,
132
+ delayed: jobs.filter((j) => j.status === "delayed").length,
133
+ };
134
+ }
135
+ /**
136
+ * Process the next available job from a queue
137
+ */
138
+ async processNext(queue) {
139
+ const processor = this.processors.get(queue);
140
+ if (!processor || !processor.running)
141
+ return;
142
+ const concurrency = processor.config.concurrency ?? 1;
143
+ if (processor.active >= concurrency)
144
+ return;
145
+ const jobs = this.jobs.get(queue);
146
+ if (!jobs || jobs.length === 0)
147
+ return;
148
+ // Check for delayed jobs that are ready
149
+ const now = Date.now();
150
+ for (const job of jobs) {
151
+ if (job.status === "delayed" && job.scheduledAt && job.scheduledAt.getTime() <= now) {
152
+ job.status = "waiting";
153
+ }
154
+ }
155
+ // Find next waiting job
156
+ const jobIdx = jobs.findIndex((j) => j.status === "waiting");
157
+ if (jobIdx < 0)
158
+ return;
159
+ const internalJob = jobs[jobIdx];
160
+ internalJob.status = "active";
161
+ processor.active++;
162
+ const workerJob = {
163
+ id: internalJob.id,
164
+ data: internalJob.data,
165
+ headers: {},
166
+ queue: internalJob.queue,
167
+ priority: internalJob.priority,
168
+ attempts: internalJob.attempts,
169
+ maxRetries: internalJob.maxRetries,
170
+ createdAt: internalJob.createdAt,
171
+ delay: internalJob.delay,
172
+ timeout: internalJob.timeout,
173
+ raw: internalJob,
174
+ complete: async () => {
175
+ internalJob.status = "completed";
176
+ const idx = jobs.indexOf(internalJob);
177
+ if (idx >= 0)
178
+ jobs.splice(idx, 1);
179
+ const s = this.stats.get(queue);
180
+ if (s)
181
+ s.completed++;
182
+ },
183
+ fail: async (error, requeue) => {
184
+ internalJob.attempts++;
185
+ internalJob.error = error;
186
+ if (requeue && internalJob.attempts < internalJob.maxRetries) {
187
+ // Requeue with backoff
188
+ const backoff = Math.min(1000 * Math.pow(2, internalJob.attempts), 30000);
189
+ internalJob.status = "delayed";
190
+ internalJob.scheduledAt = new Date(Date.now() + backoff);
191
+ }
192
+ else {
193
+ internalJob.status = "failed";
194
+ const idx = jobs.indexOf(internalJob);
195
+ if (idx >= 0)
196
+ jobs.splice(idx, 1);
197
+ const s = this.stats.get(queue);
198
+ if (s)
199
+ s.failed++;
200
+ }
201
+ },
202
+ };
203
+ try {
204
+ await processor.handler(workerJob);
205
+ }
206
+ catch {
207
+ // Handler threw - treat as failure
208
+ if (internalJob.status === "active") {
209
+ internalJob.status = "failed";
210
+ const idx = jobs.indexOf(internalJob);
211
+ if (idx >= 0)
212
+ jobs.splice(idx, 1);
213
+ const s = this.stats.get(queue);
214
+ if (s)
215
+ s.failed++;
216
+ }
217
+ }
218
+ finally {
219
+ processor.active--;
220
+ }
221
+ }
222
+ }
223
+ exports.InMemoryAdapter = InMemoryAdapter;
224
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSW5NZW1vcnlBZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FkYXB0ZXJzL0luTWVtb3J5QWRhcHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHOzs7QUFHSCwrQkFBa0M7QUFnQ2xDOztHQUVHO0FBQ0gsTUFBYSxlQUFlO0lBQ2xCLFFBQVEsR0FBRyxXQUFvQixDQUFDO0lBQ2pDLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsSUFBSSxHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQzdDLFVBQVUsR0FBZ0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNwRCxLQUFLLEdBQXVELElBQUksR0FBRyxFQUFFLENBQUM7SUFFOUUsS0FBSyxDQUFDLE9BQU87UUFDWixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztJQUN2QixDQUFDO0lBRUQsS0FBSyxDQUFDLFVBQVU7UUFDZixzQkFBc0I7UUFDdEIsS0FBSyxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNsRCxTQUFTLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztZQUMxQixJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDckIsYUFBYSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNoQyxDQUFDO1FBQ0YsQ0FBQztRQUNELElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ25CLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLENBQUM7SUFFRCxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQXlCLEVBQUUsT0FBMEM7UUFDbEYsSUFBSSxDQUFDLElB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NE5DIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBJbk1lbW9yeUFkYXB0ZXIgLSBXb3JrZXIgYWRhcHRlciB1c2luZyBpbi1wcm9jZXNzIHF1ZXVlc1xuICpcbiAqIElkZWFsIGZvcjpcbiAqIC0gRGV2ZWxvcG1lbnQgYW5kIHRlc3RpbmdcbiAqIC0gU2ltcGxlIGJhY2tncm91bmQgam9iIHByb2Nlc3NpbmdcbiAqIC0gU2luZ2xlLWluc3RhbmNlIGRlcGxveW1lbnRzXG4gKlxuICogTGltaXRhdGlvbnM6XG4gKiAtIEpvYnMgYXJlIGxvc3Qgb24gcHJvY2VzcyByZXN0YXJ0XG4gKiAtIE5vIGRpc3RyaWJ1dGVkIHByb2Nlc3NpbmdcbiAqIC0gTm8gcGVyc2lzdGVuY2VcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgYWRhcHRlciA9IG5ldyBJbk1lbW9yeUFkYXB0ZXIoKTtcbiAqIGBgYFxuICovXG5cbmltcG9ydCB0eXBlIHsgV29ya2VyVHJpZ2dlck9wdHMgfSBmcm9tIFwiQGJsb2svaGVscGVyXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcbmltcG9ydCB0eXBlIHsgV29ya2VyQWRhcHRlciwgV29ya2VySm9iLCBXb3JrZXJRdWV1ZVN0YXRzIH0gZnJvbSBcIi4uL1dvcmtlclRyaWdnZXJcIjtcblxuLyoqXG4gKiBJbnRlcm5hbCBqb2IgcmVwcmVzZW50YXRpb25cbiAqL1xuaW50ZXJmYWNlIEludGVybmFsSm9iIHtcblx0aWQ6IHN0cmluZztcblx0ZGF0YTogdW5rbm93bjtcblx0cXVldWU6IHN0cmluZztcblx0cHJpb3JpdHk6IG51bWJlcjtcblx0YXR0ZW1wdHM6IG51bWJlcjtcblx0bWF4UmV0cmllczogbnVtYmVyO1xuXHRjcmVhdGVkQXQ6IERhdGU7XG5cdGRlbGF5OiBudW1iZXI7XG5cdHRpbWVvdXQ6IG51bWJlcjtcblx0c3RhdHVzOiBcIndhaXRpbmdcIiB8IFwiYWN0aXZlXCIgfCBcImNvbXBsZXRlZFwiIHwgXCJmYWlsZWRcIiB8IFwiZGVsYXllZFwiO1xuXHRzY2hlZHVsZWRBdD86IERhdGU7XG5cdGVycm9yPzogRXJyb3I7XG59XG5cbi8qKlxuICogUXVldWUgcHJvY2Vzc29yIGVudHJ5XG4gKi9cbmludGVyZmFjZSBRdWV1ZVByb2Nlc3NvciB7XG5cdGNvbmZpZzogV29ya2VyVHJpZ2dlck9wdHM7XG5cdGhhbmRsZXI6IChqb2I6IFdvcmtlckpvYikgPT4gUHJvbWlzZTx2b2lkPjtcblx0YWN0aXZlOiBudW1iZXI7XG5cdHJ1bm5pbmc6IGJvb2xlYW47XG5cdHRpbWVyPzogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+O1xufVxuXG4vKipcbiAqIEluTWVtb3J5QWRhcHRlciAtIFNpbXBsZSBpbi1wcm9jZXNzIHdvcmtlciBxdWV1ZVxuICovXG5leHBvcnQgY2xhc3MgSW5NZW1vcnlBZGFwdGVyIGltcGxlbWVudHMgV29ya2VyQWRhcHRlciB7XG5cdHJlYWRvbmx5IHByb3ZpZGVyID0gXCJpbi1tZW1vcnlcIiBhcyBjb25zdDtcblx0cHJpdmF0ZSBjb25uZWN0ZWQgPSBmYWxzZTtcblx0cHJpdmF0ZSBqb2JzOiBNYXA8c3RyaW5nLCBJbnRlcm5hbEpvYltdPiA9IG5ldyBNYXAoKTtcblx0cHJpdmF0ZSBwcm9jZXNzb3JzOiBNYXA8c3RyaW5nLCBRdWV1ZVByb2Nlc3Nvcj4gPSBuZXcgTWFwKCk7XG5cdHByaXZhdGUgc3RhdHM6IE1hcDxzdHJpbmcsIHsgY29tcGxldGVkOiBudW1iZXI7IGZhaWxlZDogbnVtYmVyIH0+ID0gbmV3IE1hcCgpO1xuXG5cdGFzeW5jIGNvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0dGhpcy5jb25uZWN0ZWQgPSB0cnVlO1xuXHR9XG5cblx0YXN5bmMgZGlzY29ubmVjdCgpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHQvLyBTdG9wIGFsbCBwcm9jZXNzb3JzXG5cdFx0Zm9yIChjb25zdCBbcXVldWUsIHByb2Nlc3Nvcl0gb2YgdGhpcy5wcm9jZXNzb3JzKSB7XG5cdFx0XHRwcm9jZXNzb3IucnVubmluZyA9IGZhbHNlO1xuXHRcdFx0aWYgKHByb2Nlc3Nvci50aW1lcikge1xuXHRcdFx0XHRjbGVhckludGVydmFsKHByb2Nlc3Nvci50aW1lcik7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMucHJvY2Vzc29ycy5jbGVhcigpO1xuXHRcdHRoaXMuam9icy5jbGVhcigpO1xuXHRcdHRoaXMuc3RhdHMuY2xlYXIoKTtcblx0XHR0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuXHR9XG5cblx0YXN5bmMgcHJvY2Vzcyhjb25maWc6IFdvcmtlclRyaWdnZXJPcHRzLCBoYW5kbGVyOiAoam9iOiBXb3JrZXJKb2IpID0+IFByb21pc2U8dm9pZD4pOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRpZiAoIXRoaXMuY29ubmVjdGVkKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJOb3QgY29ubmVjdGVkLiBDYWxsIGNvbm5lY3QoKSBmaXJzdC5cIik7XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLmpvYnMuaGFzKGNvbmZpZy5xdWV1ZSkpIHtcblx0XHRcdHRoaXMuam9icy5zZXQoY29uZmlnLnF1ZXVlLCBbXSk7XG5cdFx0fVxuXHRcdGlmICghdGhpcy5zdGF0cy5oYXMoY29uZmlnLnF1ZXVlKSkge1xuXHRcdFx0dGhpcy5zdGF0cy5zZXQoY29uZmlnLnF1ZXVlLCB7IGNvbXBsZXRlZDogMCwgZmFpbGVkOiAwIH0pO1xuXHRcdH1cblxuXHRcdGNvbnN0IHByb2Nlc3NvcjogUXVldWVQcm9jZXNzb3IgPSB7XG5cdFx0XHRjb25maWcsXG5cdFx0XHRoYW5kbGVyLFxuXHRcdFx0YWN0aXZlOiAwLFxuXHRcdFx0cnVubmluZzogdHJ1ZSxcblx0XHR9O1xuXG5cdFx0dGhpcy5wcm9jZXNzb3JzLnNldChjb25maWcucXVldWUsIHByb2Nlc3Nvcik7XG5cblx0XHQvLyBTdGFydCBwb2xsaW5nIGZvciBqb2JzXG5cdFx0cHJvY2Vzc29yLnRpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuXHRcdFx0dGhpcy5wcm9jZXNzTmV4dChjb25maWcucXVldWUpLmNhdGNoKChlcnIpID0+IHtcblx0XHRcdFx0Y29uc29sZS5lcnJvcihgW0luTWVtb3J5QWRhcHRlcl0gRXJyb3IgcHJvY2Vzc2luZyAke2NvbmZpZy5xdWV1ZX06ICR7KGVyciBhcyBFcnJvcikubWVzc2FnZX1gKTtcblx0XHRcdH0pO1xuXHRcdH0sIDUwKTsgLy8gUG9sbCBldmVyeSA1MG1zXG5cdH1cblxuXHRhc3luYyBhZGRKb2IoXG5cdFx0cXVldWU6IHN0cmluZyxcblx0XHRkYXRhOiB1bmtub3duLFxuXHRcdG9wdHM/OiB7XG5cdFx0XHRwcmlvcml0eT86IG51bWJlcjtcblx0XHRcdGRlbGF5PzogbnVtYmVyO1xuXHRcdFx0cmV0cmllcz86IG51bWJlcjtcblx0XHRcdHRpbWVvdXQ/OiBudW1iZXI7XG5cdFx0XHRqb2JJZD86IHN0cmluZztcblx0XHR9LFxuXHQpOiBQcm9taXNlPHN0cmluZz4ge1xuXHRcdGlmICghdGhpcy5jb25uZWN0ZWQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIk5vdCBjb25uZWN0ZWQuIENhbGwgY29ubmVjdCgpIGZpcnN0LlwiKTtcblx0XHR9XG5cblx0XHRpZiAoIXRoaXMuam9icy5oYXMocXVldWUpKSB7XG5cdFx0XHR0aGlzLmpvYnMuc2V0KHF1ZXVlLCBbXSk7XG5cdFx0fVxuXHRcdGlmICghdGhpcy5zdGF0cy5oYXMocXVldWUpKSB7XG5cdFx0XHR0aGlzLnN0YXRzLnNldChxdWV1ZSwgeyBjb21wbGV0ZWQ6IDAsIGZhaWxlZDogMCB9KTtcblx0XHR9XG5cblx0XHRjb25zdCBqb2I6IEludGVybmFsSm9iID0ge1xuXHRcdFx0aWQ6IG9wdHM/LmpvYklkIHx8IHV1aWQoKSxcblx0XHRcdGRhdGEsXG5cdFx0XHRxdWV1ZSxcblx0XHRcdHByaW9yaXR5OiBvcHRzPy5wcmlvcml0eSA/PyAwLFxuXHRcdFx0YXR0ZW1wdHM6IDAsXG5cdFx0XHRtYXhSZXRyaWVzOiBvcHRzPy5yZXRyaWVzID8/IDMsXG5cdFx0XHRjcmVhdGVkQXQ6IG5ldyBEYXRlKCksXG5cdFx0XHRkZWxheTogb3B0cz8uZGVsYXkgPz8gMCxcblx0XHRcdHRpbWVvdXQ6IG9wdHM/LnRpbWVvdXQgPz8gMCxcblx0XHRcdHN0YXR1czogb3B0cz8uZGVsYXkgJiYgb3B0cy5kZWxheSA+IDAgPyBcImRlbGF5ZWRcIiA6IFwid2FpdGluZ1wiLFxuXHRcdH07XG5cblx0XHRpZiAoam9iLnN0YXR1cyA9PT0gXCJkZWxheWVkXCIpIHtcblx0XHRcdGpvYi5zY2hlZHVsZWRBdCA9IG5ldyBEYXRlKERhdGUubm93KCkgKyBqb2IuZGVsYXkpO1xuXHRcdH1cblxuXHRcdGNvbnN0IGpvYnMgPSB0aGlzLmpvYnMuZ2V0KHF1ZXVlKSE7XG5cblx0XHQvLyBJbnNlcnQgc29ydGVkIGJ5IHByaW9yaXR5IChoaWdoZXIgZmlyc3QpXG5cdFx0Y29uc3QgaW5zZXJ0SWR4ID0gam9icy5maW5kSW5kZXgoKGopID0+IGouc3RhdHVzID09PSBcIndhaXRpbmdcIiAmJiBqLnByaW9yaXR5IDwgam9iLnByaW9yaXR5KTtcblx0XHRpZiAoaW5zZXJ0SWR4ID49IDApIHtcblx0XHRcdGpvYnMuc3BsaWNlKGluc2VydElkeCwgMCwgam9iKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0am9icy5wdXNoKGpvYik7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGpvYi5pZDtcblx0fVxuXG5cdGFzeW5jIHN0b3BQcm9jZXNzaW5nKHF1ZXVlOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRjb25zdCBwcm9jZXNzb3IgPSB0aGlzLnByb2Nlc3NvcnMuZ2V0KHF1ZXVlKTtcblx0XHRpZiAocHJvY2Vzc29yKSB7XG5cdFx0XHRwcm9jZXNzb3IucnVubmluZyA9IGZhbHNlO1xuXHRcdFx0aWYgKHByb2Nlc3Nvci50aW1lcikge1xuXHRcdFx0XHRjbGVhckludGVydmFsKHByb2Nlc3Nvci50aW1lcik7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnByb2Nlc3NvcnMuZGVsZXRlKHF1ZXVlKTtcblx0XHR9XG5cdH1cblxuXHRpc0Nvbm5lY3RlZCgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5jb25uZWN0ZWQ7XG5cdH1cblxuXHRhc3luYyBoZWFsdGhDaGVjaygpOiBQcm9taXNlPGJvb2xlYW4+IHtcblx0XHRyZXR1cm4gdGhpcy5jb25uZWN0ZWQ7XG5cdH1cblxuXHRhc3luYyBnZXRRdWV1ZVN0YXRzKHF1ZXVlOiBzdHJpbmcpOiBQcm9taXNlPFdvcmtlclF1ZXVlU3RhdHM+IHtcblx0XHRjb25zdCBqb2JzID0gdGhpcy5qb2JzLmdldChxdWV1ZSkgfHwgW107XG5cdFx0Y29uc3QgcXVldWVTdGF0cyA9IHRoaXMuc3RhdHMuZ2V0KHF1ZXVlKSB8fCB7IGNvbXBsZXRlZDogMCwgZmFpbGVkOiAwIH07XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0d2FpdGluZzogam9icy5maWx0ZXIoKGopID0+IGouc3RhdHVzID09PSBcIndhaXRpbmdcIikubGVuZ3RoLFxuXHRcdFx0YWN0aXZlOiBqb2JzLmZpbHRlcigoaikgPT4gai5zdGF0dXMgPT09IFwiYWN0aXZlXCIpLmxlbmd0aCxcblx0XHRcdGNvbXBsZXRlZDogcXVldWVTdGF0cy5jb21wbGV0ZWQsXG5cdFx0XHRmYWlsZWQ6IHF1ZXVlU3RhdHMuZmFpbGVkLFxuXHRcdFx0ZGVsYXllZDogam9icy5maWx0ZXIoKGopID0+IGouc3RhdHVzID09PSBcImRlbGF5ZWRcIikubGVuZ3RoLFxuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogUHJvY2VzcyB0aGUgbmV4dCBhdmFpbGFibGUgam9iIGZyb20gYSBxdWV1ZVxuXHQgKi9cblx0cHJpdmF0ZSBhc3luYyBwcm9jZXNzTmV4dChxdWV1ZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0Y29uc3QgcHJvY2Vzc29yID0gdGhpcy5wcm9jZXNzb3JzLmdldChxdWV1ZSk7XG5cdFx0aWYgKCFwcm9jZXNzb3IgfHwgIXByb2Nlc3Nvci5ydW5uaW5nKSByZXR1cm47XG5cblx0XHRjb25zdCBjb25jdXJyZW5jeSA9IHByb2Nlc3Nvci5jb25maWcuY29uY3VycmVuY3kgPz8gMTtcblx0XHRpZiAocHJvY2Vzc29yLmFjdGl2ZSA+PSBjb25jdXJyZW5jeSkgcmV0dXJuO1xuXG5cdFx0Y29uc3Qgam9icyA9IHRoaXMuam9icy5nZXQocXVldWUpO1xuXHRcdGlmICgham9icyB8fCBqb2JzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG5cdFx0Ly8gQ2hlY2sgZm9yIGRlbGF5ZWQgam9icyB0aGF0IGFyZSByZWFkeVxuXHRcdGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG5cdFx0Zm9yIChjb25zdCBqb2Igb2Ygam9icykge1xuXHRcdFx0aWYgKGpvYi5zdGF0dXMgPT09IFwiZGVsYXllZFwiICYmIGpvYi5zY2hlZHVsZWRBdCAmJiBqb2Iuc2NoZWR1bGVkQXQuZ2V0VGltZSgpIDw9IG5vdykge1xuXHRcdFx0XHRqb2Iuc3RhdHVzID0gXCJ3YWl0aW5nXCI7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmluZCBuZXh0IHdhaXRpbmcgam9iXG5cdFx0Y29uc3Qgam9iSWR4ID0gam9icy5maW5kSW5kZXgoKGopID0+IGouc3RhdHVzID09PSBcIndhaXRpbmdcIik7XG5cdFx0aWYgKGpvYklkeCA8IDApIHJldHVybjtcblxuXHRcdGNvbnN0IGludGVybmFsSm9iID0gam9ic1tqb2JJZHhdO1xuXHRcdGludGVybmFsSm9iLnN0YXR1cyA9IFwiYWN0aXZlXCI7XG5cdFx0cHJvY2Vzc29yLmFjdGl2ZSsrO1xuXG5cdFx0Y29uc3Qgd29ya2VySm9iOiBXb3JrZXJKb2IgPSB7XG5cdFx0XHRpZDogaW50ZXJuYWxKb2IuaWQsXG5cdFx0XHRkYXRhOiBpbnRlcm5hbEpvYi5kYXRhLFxuXHRcdFx0aGVhZGVyczoge30sXG5cdFx0XHRxdWV1ZTogaW50ZXJuYWxKb2IucXVldWUsXG5cdFx0XHRwcmlvcml0eTogaW50ZXJuYWxKb2IucHJpb3JpdHksXG5cdFx0XHRhdHRlbXB0czogaW50ZXJuYWxKb2IuYXR0ZW1wdHMsXG5cdFx0XHRtYXhSZXRyaWVzOiBpbnRlcm5hbEpvYi5tYXhSZXRyaWVzLFxuXHRcdFx0Y3JlYXRlZEF0OiBpbnRlcm5hbEpvYi5jcmVhdGVkQXQsXG5cdFx0XHRkZWxheTogaW50ZXJuYWxKb2IuZGVsYXksXG5cdFx0XHR0aW1lb3V0OiBpbnRlcm5hbEpvYi50aW1lb3V0LFxuXHRcdFx0cmF3OiBpbnRlcm5hbEpvYixcblx0XHRcdGNvbXBsZXRlOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdGludGVybmFsSm9iLnN0YXR1cyA9IFwiY29tcGxldGVkXCI7XG5cdFx0XHRcdGNvbnN0IGlkeCA9IGpvYnMuaW5kZXhPZihpbnRlcm5hbEpvYik7XG5cdFx0XHRcdGlmIChpZHggPj0gMCkgam9icy5zcGxpY2UoaWR4LCAxKTtcblx0XHRcdFx0Y29uc3QgcyA9IHRoaXMuc3RhdHMuZ2V0KHF1ZXVlKTtcblx0XHRcdFx0aWYgKHMpIHMuY29tcGxldGVkKys7XG5cdFx0XHR9LFxuXHRcdFx0ZmFpbDogYXN5bmMgKGVycm9yOiBFcnJvciwgcmVxdWV1ZT86IGJvb2xlYW4pID0+IHtcblx0XHRcdFx0aW50ZXJuYWxKb2IuYXR0ZW1wdHMrKztcblx0XHRcdFx0aW50ZXJuYWxKb2IuZXJyb3IgPSBlcnJvcjtcblxuXHRcdFx0XHRpZiAocmVxdWV1ZSAmJiBpbnRlcm5hbEpvYi5hdHRlbXB0cyA8IGludGVybmFsSm9iLm1heFJldHJpZXMpIHtcblx0XHRcdFx0XHQvLyBSZXF1ZXVlIHdpdGggYmFja29mZlxuXHRcdFx0XHRcdGNvbnN0IGJhY2tvZmYgPSBNYXRoLm1pbigxMDAwICogTWF0aC5wb3coMiwgaW50ZXJuYWxKb2IuYXR0ZW1wdHMpLCAzMDAwMCk7XG5cdFx0XHRcdFx0aW50ZXJuYWxKb2Iuc3RhdHVzID0gXCJkZWxheWVkXCI7XG5cdFx0XHRcdFx0aW50ZXJuYWxKb2Iuc2NoZWR1bGVkQXQgPSBuZXcgRGF0ZShEYXRlLm5vdygpICsgYmFja29mZik7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aW50ZXJuYWxKb2Iuc3RhdHVzID0gXCJmYWlsZWRcIjtcblx0XHRcdFx0XHRjb25zdCBpZHggPSBqb2JzLmluZGV4T2YoaW50ZXJuYWxKb2IpO1xuXHRcdFx0XHRcdGlmIChpZHggPj0gMCkgam9icy5zcGxpY2UoaWR4LCAxKTtcblx0XHRcdFx0XHRjb25zdCBzID0gdGhpcy5zdGF0cy5nZXQocXVldWUpO1xuXHRcdFx0XHRcdGlmIChzKSBzLmZhaWxlZCsrO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdH07XG5cblx0XHR0cnkge1xuXHRcdFx0YXdhaXQgcHJvY2Vzc29yLmhhbmRsZXIod29ya2VySm9iKTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdC8vIEhhbmRsZXIgdGhyZXcgLSB0cmVhdCBhcyBmYWlsdXJlXG5cdFx0XHRpZiAoaW50ZXJuYWxKb2Iuc3RhdHVzID09PSBcImFjdGl2ZVwiKSB7XG5cdFx0XHRcdGludGVybmFsSm9iLnN0YXR1cyA9IFwiZmFpbGVkXCI7XG5cdFx0XHRcdGNvbnN0IGlkeCA9IGpvYnMuaW5kZXhPZihpbnRlcm5hbEpvYik7XG5cdFx0XHRcdGlmIChpZHggPj0gMCkgam9icy5zcGxpY2UoaWR4LCAxKTtcblx0XHRcdFx0Y29uc3QgcyA9IHRoaXMuc3RhdHMuZ2V0KHF1ZXVlKTtcblx0XHRcdFx0aWYgKHMpIHMuZmFpbGVkKys7XG5cdFx0XHR9XG5cdFx0fSBmaW5hbGx5IHtcblx0XHRcdHByb2Nlc3Nvci5hY3RpdmUtLTtcblx0XHR9XG5cdH1cbn1cbiJdfQ==
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @blok/trigger-worker
3
+ *
4
+ * Worker-based trigger for Blok workflows.
5
+ * Supports background job processing with:
6
+ * - Configurable concurrency per queue
7
+ * - Automatic retries with exponential backoff
8
+ * - Job timeouts
9
+ * - Priority-based job ordering
10
+ * - Delayed job scheduling
11
+ * - Queue statistics and monitoring
12
+ *
13
+ * Adapters:
14
+ * - BullMQ (Redis-backed, production)
15
+ * - InMemory (development/testing)
16
+ *
17
+ * @example BullMQ
18
+ * ```typescript
19
+ * import { WorkerTrigger, BullMQAdapter } from "@blok/trigger-worker";
20
+ *
21
+ * class MyWorkerTrigger extends WorkerTrigger {
22
+ * protected adapter = new BullMQAdapter({
23
+ * host: "localhost",
24
+ * port: 6379,
25
+ * });
26
+ *
27
+ * protected nodes = myNodes;
28
+ * protected workflows = myWorkflows;
29
+ * }
30
+ *
31
+ * const trigger = new MyWorkerTrigger();
32
+ * await trigger.listen();
33
+ *
34
+ * // Dispatch a job
35
+ * await trigger.dispatch("background-jobs", { userId: "123" }, {
36
+ * priority: 10,
37
+ * retries: 3,
38
+ * delay: 5000, // delay 5 seconds
39
+ * });
40
+ * ```
41
+ *
42
+ * @example InMemory (development)
43
+ * ```typescript
44
+ * import { WorkerTrigger, InMemoryAdapter } from "@blok/trigger-worker";
45
+ *
46
+ * class DevWorkerTrigger extends WorkerTrigger {
47
+ * protected adapter = new InMemoryAdapter();
48
+ * protected nodes = myNodes;
49
+ * protected workflows = myWorkflows;
50
+ * }
51
+ * ```
52
+ */
53
+ export { WorkerTrigger, type WorkerAdapter, type WorkerJob, type WorkerQueueStats, } from "./WorkerTrigger";
54
+ export { BullMQAdapter, type BullMQConfig } from "./adapters/BullMQAdapter";
55
+ export { InMemoryAdapter } from "./adapters/InMemoryAdapter";
56
+ export type { WorkerTriggerOpts } from "@blok/helper";