workmatic 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.
package/dist/worker.js ADDED
@@ -0,0 +1,331 @@
1
+ import fastq from 'fastq';
2
+ import { sql } from 'kysely';
3
+ import { defaultBackoff, parsePayload, now } from './utils.js';
4
+ /**
5
+ * Create a job queue worker for processing jobs
6
+ *
7
+ * @param options - Worker options
8
+ * @returns Worker instance
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const worker = createWorker({ db, concurrency: 4 });
13
+ *
14
+ * // Set the processor function
15
+ * worker.process(async (job) => {
16
+ * console.log('Processing job:', job.id);
17
+ * await sendEmail(job.payload.email);
18
+ * });
19
+ *
20
+ * // Start processing
21
+ * worker.start();
22
+ *
23
+ * // Later, gracefully stop
24
+ * await worker.stop();
25
+ * ```
26
+ */
27
+ export function createWorker(options) {
28
+ const { db, queue = 'default', concurrency = 1, leaseMs = 30000, pollMs = 1000, timeoutMs, backoff = defaultBackoff, } = options;
29
+ if (!db) {
30
+ throw new Error('Database instance is required');
31
+ }
32
+ // State
33
+ let running = false;
34
+ let paused = false;
35
+ let processor = null;
36
+ let pumpTimeout = null;
37
+ let fastqQueue = null;
38
+ /**
39
+ * Requeue jobs with expired leases
40
+ */
41
+ async function requeueExpiredLeases() {
42
+ const timestamp = now();
43
+ const result = await db
44
+ .updateTable('workmatic_jobs')
45
+ .set({
46
+ status: 'ready',
47
+ lease_until: 0,
48
+ updated_at: timestamp,
49
+ })
50
+ .where('status', '=', 'running')
51
+ .where('lease_until', '<', timestamp)
52
+ .where('lease_until', '>', 0)
53
+ .execute();
54
+ return Number(result[0]?.numUpdatedRows ?? 0);
55
+ }
56
+ /**
57
+ * Claim a batch of jobs for processing
58
+ */
59
+ async function claimBatch(limit) {
60
+ const timestamp = now();
61
+ const leaseUntil = timestamp + leaseMs;
62
+ // Use a transaction to ensure atomic claim
63
+ return await db.transaction().execute(async (trx) => {
64
+ // Select eligible jobs
65
+ const jobs = await trx
66
+ .selectFrom('workmatic_jobs')
67
+ .select(['id', 'public_id', 'queue', 'payload', 'attempts', 'max_attempts'])
68
+ .where('queue', '=', queue)
69
+ .where('status', '=', 'ready')
70
+ .where('run_at', '<=', timestamp)
71
+ .orderBy('priority', 'asc')
72
+ .orderBy('id', 'asc')
73
+ .limit(limit)
74
+ .execute();
75
+ if (jobs.length === 0) {
76
+ return [];
77
+ }
78
+ // Get the IDs of claimed jobs
79
+ const jobIds = jobs.map(j => j.id);
80
+ // Update them to running status
81
+ await trx
82
+ .updateTable('workmatic_jobs')
83
+ .set({
84
+ status: 'running',
85
+ lease_until: leaseUntil,
86
+ updated_at: timestamp,
87
+ })
88
+ .where('id', 'in', jobIds)
89
+ .execute();
90
+ return jobs;
91
+ });
92
+ }
93
+ /**
94
+ * Mark a job as completed
95
+ */
96
+ async function markDone(jobId) {
97
+ await db
98
+ .updateTable('workmatic_jobs')
99
+ .set({
100
+ status: 'done',
101
+ lease_until: 0,
102
+ updated_at: now(),
103
+ })
104
+ .where('id', '=', jobId)
105
+ .execute();
106
+ }
107
+ /**
108
+ * Handle job failure
109
+ */
110
+ async function markFailed(jobId, attempts, maxAttempts, error) {
111
+ const timestamp = now();
112
+ const newAttempts = attempts + 1;
113
+ const errorMessage = error.message || String(error);
114
+ if (newAttempts < maxAttempts) {
115
+ // Retry: set back to ready with backoff delay
116
+ const runAt = timestamp + backoff(newAttempts);
117
+ await db
118
+ .updateTable('workmatic_jobs')
119
+ .set({
120
+ status: 'ready',
121
+ attempts: newAttempts,
122
+ run_at: runAt,
123
+ lease_until: 0,
124
+ last_error: errorMessage,
125
+ updated_at: timestamp,
126
+ })
127
+ .where('id', '=', jobId)
128
+ .execute();
129
+ }
130
+ else {
131
+ // Max attempts reached: mark as dead
132
+ await db
133
+ .updateTable('workmatic_jobs')
134
+ .set({
135
+ status: 'dead',
136
+ attempts: newAttempts,
137
+ lease_until: 0,
138
+ last_error: errorMessage,
139
+ updated_at: timestamp,
140
+ })
141
+ .where('id', '=', jobId)
142
+ .execute();
143
+ }
144
+ }
145
+ /**
146
+ * Run a promise with timeout
147
+ */
148
+ async function withTimeout(promise, ms, jobId) {
149
+ let timeoutId;
150
+ const timeoutPromise = new Promise((_, reject) => {
151
+ timeoutId = setTimeout(() => {
152
+ reject(new Error(`Job ${jobId} timed out after ${ms}ms`));
153
+ }, ms);
154
+ });
155
+ try {
156
+ return await Promise.race([promise, timeoutPromise]);
157
+ }
158
+ finally {
159
+ clearTimeout(timeoutId);
160
+ }
161
+ }
162
+ /**
163
+ * Process a single job
164
+ */
165
+ async function processJob(claimedJob) {
166
+ if (!processor) {
167
+ throw new Error('No processor set');
168
+ }
169
+ // Parse payload and create job object
170
+ const payload = parsePayload(claimedJob.payload);
171
+ const job = {
172
+ id: claimedJob.public_id,
173
+ queue: claimedJob.queue,
174
+ payload,
175
+ status: 'running',
176
+ priority: 0, // Not needed for processing
177
+ attempts: claimedJob.attempts,
178
+ maxAttempts: claimedJob.max_attempts,
179
+ createdAt: 0, // Not needed for processing
180
+ lastError: null,
181
+ };
182
+ try {
183
+ // Run processor with optional timeout
184
+ if (timeoutMs) {
185
+ await withTimeout(processor(job), timeoutMs, job.id);
186
+ }
187
+ else {
188
+ await processor(job);
189
+ }
190
+ await markDone(claimedJob.id);
191
+ }
192
+ catch (error) {
193
+ await markFailed(claimedJob.id, claimedJob.attempts, claimedJob.max_attempts, error instanceof Error ? error : new Error(String(error)));
194
+ }
195
+ }
196
+ /**
197
+ * Check if queue is paused in database (for CLI control)
198
+ */
199
+ async function isQueuePausedInDb() {
200
+ const setting = await db
201
+ .selectFrom('workmatic_settings')
202
+ .select('paused')
203
+ .where('queue', '=', queue)
204
+ .executeTakeFirst();
205
+ return setting?.paused === 1;
206
+ }
207
+ /**
208
+ * Main pump loop
209
+ */
210
+ async function pump() {
211
+ if (!running) {
212
+ return;
213
+ }
214
+ // Check both in-memory pause and database pause (for CLI control)
215
+ if (paused) {
216
+ pumpTimeout = setTimeout(pump, pollMs);
217
+ return;
218
+ }
219
+ try {
220
+ // Check database pause state (allows CLI to pause running workers)
221
+ const dbPaused = await isQueuePausedInDb();
222
+ if (dbPaused) {
223
+ pumpTimeout = setTimeout(pump, pollMs);
224
+ return;
225
+ }
226
+ // Requeue expired leases
227
+ await requeueExpiredLeases();
228
+ // Claim a batch of jobs
229
+ const batchSize = concurrency * 2;
230
+ const jobs = await claimBatch(batchSize);
231
+ if (jobs.length > 0) {
232
+ // Push jobs into fastq
233
+ for (const job of jobs) {
234
+ fastqQueue.push(job);
235
+ }
236
+ // Immediately pump again
237
+ pumpTimeout = setTimeout(pump, 0);
238
+ }
239
+ else {
240
+ // No jobs, wait before polling again
241
+ pumpTimeout = setTimeout(pump, pollMs);
242
+ }
243
+ }
244
+ catch (error) {
245
+ // Log error and continue
246
+ console.error('[workmatic] Pump error:', error);
247
+ pumpTimeout = setTimeout(pump, pollMs);
248
+ }
249
+ }
250
+ // Create the worker object
251
+ const worker = {
252
+ process(fn) {
253
+ processor = fn;
254
+ },
255
+ start() {
256
+ if (running) {
257
+ return;
258
+ }
259
+ if (!processor) {
260
+ throw new Error('No processor set. Call process() before start()');
261
+ }
262
+ running = true;
263
+ paused = false;
264
+ // Create fastq queue
265
+ fastqQueue = fastq.promise(processJob, concurrency);
266
+ // Start pump loop
267
+ pump();
268
+ },
269
+ async stop() {
270
+ if (!running) {
271
+ return;
272
+ }
273
+ running = false;
274
+ // Clear pump timeout
275
+ if (pumpTimeout) {
276
+ clearTimeout(pumpTimeout);
277
+ pumpTimeout = null;
278
+ }
279
+ // Wait for fastq to drain
280
+ if (fastqQueue) {
281
+ await fastqQueue.drained();
282
+ fastqQueue = null;
283
+ }
284
+ },
285
+ pause() {
286
+ paused = true;
287
+ },
288
+ resume() {
289
+ paused = false;
290
+ },
291
+ async stats() {
292
+ const result = await db
293
+ .selectFrom('workmatic_jobs')
294
+ .select([
295
+ 'status',
296
+ sql `count(*)`.as('count'),
297
+ ])
298
+ .where('queue', '=', queue)
299
+ .groupBy('status')
300
+ .execute();
301
+ const stats = {
302
+ ready: 0,
303
+ running: 0,
304
+ done: 0,
305
+ failed: 0,
306
+ dead: 0,
307
+ total: 0,
308
+ };
309
+ for (const row of result) {
310
+ const status = row.status;
311
+ const count = Number(row.count);
312
+ if (status in stats) {
313
+ stats[status] = count;
314
+ }
315
+ stats.total += count;
316
+ }
317
+ return stats;
318
+ },
319
+ get isRunning() {
320
+ return running;
321
+ },
322
+ get isPaused() {
323
+ return paused;
324
+ },
325
+ get queue() {
326
+ return queue;
327
+ },
328
+ };
329
+ return worker;
330
+ }
331
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "workmatic",
3
+ "version": "1.0.0",
4
+ "description": "A persistent job queue for Node.js using SQLite",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "workmatic": "./dist/cli.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "dashboard"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "bench": "tsx benchmarks/run.ts",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "job-queue",
31
+ "task-queue",
32
+ "sqlite",
33
+ "persistent",
34
+ "background-jobs",
35
+ "worker"
36
+ ],
37
+ "author": "",
38
+ "license": "MIT",
39
+ "dependencies": {
40
+ "better-sqlite3": "^11.7.0",
41
+ "fastq": "^1.18.0",
42
+ "kysely": "^0.27.5",
43
+ "nanoid": "^5.0.9"
44
+ },
45
+ "devDependencies": {
46
+ "@types/better-sqlite3": "^7.6.12",
47
+ "@types/node": "^22.10.7",
48
+ "tsx": "^4.21.0",
49
+ "typescript": "^5.7.3",
50
+ "vitest": "^2.1.8"
51
+ },
52
+ "engines": {
53
+ "node": ">=18.0.0"
54
+ }
55
+ }