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/README.md +508 -0
- package/dashboard/app.js +249 -0
- package/dashboard/index.html +143 -0
- package/dashboard/style.css +464 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +505 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +28 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +99 -0
- package/dist/client.js.map +1 -0
- package/dist/dashboard.d.ts +48 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +412 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/database.d.ts +29 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +99 -0
- package/dist/database.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +218 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +45 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +64 -0
- package/dist/utils.js.map +1 -0
- package/dist/worker.d.ts +26 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +331 -0
- package/dist/worker.js.map +1 -0
- package/package.json +55 -0
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
|
+
}
|