workmatic 1.0.0 → 1.0.2
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/cli.cjs +559 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +0 -14
- package/dist/cli.js +400 -369
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +736 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +368 -0
- package/dist/index.d.ts +365 -9
- package/dist/index.js +688 -12
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
- package/dist/cli.d.ts.map +0 -1
- package/dist/client.d.ts +0 -28
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -99
- package/dist/client.js.map +0 -1
- package/dist/dashboard.d.ts +0 -48
- package/dist/dashboard.d.ts.map +0 -1
- package/dist/dashboard.js +0 -412
- package/dist/dashboard.js.map +0 -1
- package/dist/database.d.ts +0 -29
- package/dist/database.d.ts.map +0 -1
- package/dist/database.js +0 -99
- package/dist/database.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/types.d.ts +0 -218
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts +0 -45
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -64
- package/dist/utils.js.map +0 -1
- package/dist/worker.d.ts +0 -26
- package/dist/worker.d.ts.map +0 -1
- package/dist/worker.js +0 -331
- package/dist/worker.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,368 @@
|
|
|
1
|
+
import * as http from 'http';
|
|
2
|
+
import * as better_sqlite3 from 'better-sqlite3';
|
|
3
|
+
import { Kysely, Generated } from 'kysely';
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
|
-
*
|
|
6
|
+
* Job status types
|
|
7
|
+
*/
|
|
8
|
+
type JobStatus = 'ready' | 'running' | 'done' | 'failed' | 'dead';
|
|
9
|
+
/**
|
|
10
|
+
* Database table schema for workmatic_jobs
|
|
11
|
+
*/
|
|
12
|
+
interface WorkmaticJobsTable {
|
|
13
|
+
id: Generated<number>;
|
|
14
|
+
public_id: string;
|
|
15
|
+
queue: string;
|
|
16
|
+
payload: string;
|
|
17
|
+
status: JobStatus;
|
|
18
|
+
priority: number;
|
|
19
|
+
run_at: number;
|
|
20
|
+
attempts: number;
|
|
21
|
+
max_attempts: number;
|
|
22
|
+
lease_until: number;
|
|
23
|
+
created_at: number;
|
|
24
|
+
updated_at: number;
|
|
25
|
+
last_error: string | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Database table schema for workmatic_settings
|
|
29
|
+
*/
|
|
30
|
+
interface WorkmaticSettingsTable {
|
|
31
|
+
queue: string;
|
|
32
|
+
paused: number;
|
|
33
|
+
updated_at: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Kysely database schema
|
|
37
|
+
*/
|
|
38
|
+
interface WorkmaticDatabase {
|
|
39
|
+
workmatic_jobs: WorkmaticJobsTable;
|
|
40
|
+
workmatic_settings: WorkmaticSettingsTable;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Kysely database instance type
|
|
44
|
+
*/
|
|
45
|
+
type WorkmaticDb = Kysely<WorkmaticDatabase>;
|
|
46
|
+
/**
|
|
47
|
+
* Job representation returned to users
|
|
48
|
+
*/
|
|
49
|
+
interface Job<TPayload = unknown> {
|
|
50
|
+
/** Unique public identifier (nanoid) */
|
|
51
|
+
id: string;
|
|
52
|
+
/** Queue name */
|
|
53
|
+
queue: string;
|
|
54
|
+
/** Job payload */
|
|
55
|
+
payload: TPayload;
|
|
56
|
+
/** Current status */
|
|
57
|
+
status: JobStatus;
|
|
58
|
+
/** Priority (lower = higher priority) */
|
|
59
|
+
priority: number;
|
|
60
|
+
/** Number of attempts made */
|
|
61
|
+
attempts: number;
|
|
62
|
+
/** Maximum allowed attempts */
|
|
63
|
+
maxAttempts: number;
|
|
64
|
+
/** When the job was created (unix ms) */
|
|
65
|
+
createdAt: number;
|
|
66
|
+
/** Last error message if failed */
|
|
67
|
+
lastError: string | null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Options for adding a job
|
|
71
|
+
*/
|
|
72
|
+
interface AddJobOptions {
|
|
73
|
+
/** Job priority (lower = higher priority). Default: 0 */
|
|
74
|
+
priority?: number;
|
|
75
|
+
/** Delay before job becomes available (ms). Default: 0 */
|
|
76
|
+
delayMs?: number;
|
|
77
|
+
/** Maximum retry attempts. Default: 3 */
|
|
78
|
+
maxAttempts?: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Result of adding a job
|
|
82
|
+
*/
|
|
83
|
+
interface AddJobResult {
|
|
84
|
+
ok: true;
|
|
85
|
+
id: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Options for creating a database
|
|
89
|
+
*/
|
|
90
|
+
interface DatabaseOptions {
|
|
91
|
+
/** Existing better-sqlite3 Database instance */
|
|
92
|
+
db?: better_sqlite3.Database;
|
|
93
|
+
/** Path to SQLite database file (ignored if db is provided) */
|
|
94
|
+
filename?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Options for creating a client
|
|
98
|
+
*/
|
|
99
|
+
interface ClientOptions {
|
|
100
|
+
/** Kysely database instance */
|
|
101
|
+
db: WorkmaticDb;
|
|
102
|
+
/** Queue name. Default: 'default' */
|
|
103
|
+
queue?: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Backoff function type
|
|
107
|
+
*/
|
|
108
|
+
type BackoffFunction = (attempts: number) => number;
|
|
109
|
+
/**
|
|
110
|
+
* Options for creating a worker
|
|
111
|
+
*/
|
|
112
|
+
interface WorkerOptions {
|
|
113
|
+
/** Kysely database instance */
|
|
114
|
+
db: WorkmaticDb;
|
|
115
|
+
/** Queue name. Default: 'default' */
|
|
116
|
+
queue?: string;
|
|
117
|
+
/** Number of concurrent job processors. Default: 1 */
|
|
118
|
+
concurrency?: number;
|
|
119
|
+
/** Lease duration in ms. Default: 30000 */
|
|
120
|
+
leaseMs?: number;
|
|
121
|
+
/** Poll interval in ms when no jobs available. Default: 1000 */
|
|
122
|
+
pollMs?: number;
|
|
123
|
+
/** Job execution timeout in ms. Default: undefined (no timeout) */
|
|
124
|
+
timeoutMs?: number;
|
|
125
|
+
/** Backoff function for retries. Default: exponential */
|
|
126
|
+
backoff?: BackoffFunction;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Job processor function type
|
|
130
|
+
*/
|
|
131
|
+
type JobProcessor<TPayload = unknown> = (job: Job<TPayload>) => Promise<void>;
|
|
132
|
+
/**
|
|
133
|
+
* Stats by status
|
|
134
|
+
*/
|
|
135
|
+
interface JobStats {
|
|
136
|
+
ready: number;
|
|
137
|
+
running: number;
|
|
138
|
+
done: number;
|
|
139
|
+
failed: number;
|
|
140
|
+
dead: number;
|
|
141
|
+
total: number;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Client interface
|
|
145
|
+
*/
|
|
146
|
+
interface WorkmaticClient {
|
|
147
|
+
/** Add a job to the queue */
|
|
148
|
+
add<TPayload = unknown>(payload: TPayload, options?: AddJobOptions): Promise<AddJobResult>;
|
|
149
|
+
/** Get job statistics */
|
|
150
|
+
stats(): Promise<JobStats>;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Worker interface
|
|
154
|
+
*/
|
|
155
|
+
interface WorkmaticWorker {
|
|
156
|
+
/** Set the job processor function */
|
|
157
|
+
process<TPayload = unknown>(fn: JobProcessor<TPayload>): void;
|
|
158
|
+
/** Start processing jobs */
|
|
159
|
+
start(): void;
|
|
160
|
+
/** Stop processing jobs (drains current jobs) */
|
|
161
|
+
stop(): Promise<void>;
|
|
162
|
+
/** Pause processing (stops claiming new jobs) */
|
|
163
|
+
pause(): void;
|
|
164
|
+
/** Resume processing */
|
|
165
|
+
resume(): void;
|
|
166
|
+
/** Get job statistics */
|
|
167
|
+
stats(): Promise<JobStats>;
|
|
168
|
+
/** Check if worker is running */
|
|
169
|
+
readonly isRunning: boolean;
|
|
170
|
+
/** Check if worker is paused */
|
|
171
|
+
readonly isPaused: boolean;
|
|
172
|
+
/** Queue name */
|
|
173
|
+
readonly queue: string;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Options for creating a dashboard
|
|
177
|
+
*/
|
|
178
|
+
interface DashboardOptions {
|
|
179
|
+
/** Kysely database instance */
|
|
180
|
+
db: WorkmaticDb;
|
|
181
|
+
/** HTTP server port. Default: 3000 */
|
|
182
|
+
port?: number;
|
|
183
|
+
/** Worker instances to control */
|
|
184
|
+
workers?: WorkmaticWorker[];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Options for creating dashboard middleware
|
|
188
|
+
*/
|
|
189
|
+
interface DashboardMiddlewareOptions {
|
|
190
|
+
/** Kysely database instance */
|
|
191
|
+
db: WorkmaticDb;
|
|
192
|
+
/** Worker instances to control */
|
|
193
|
+
workers?: WorkmaticWorker[];
|
|
194
|
+
/** Base path for mounting (e.g., '/workmatic'). Default: '' */
|
|
195
|
+
basePath?: string;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Express-compatible request handler
|
|
199
|
+
*/
|
|
200
|
+
type DashboardMiddleware = (req: http.IncomingMessage, res: http.ServerResponse, next?: () => void) => void;
|
|
201
|
+
/**
|
|
202
|
+
* Dashboard interface
|
|
203
|
+
*/
|
|
204
|
+
interface WorkmaticDashboard {
|
|
205
|
+
/** Close the dashboard server */
|
|
206
|
+
close(): Promise<void>;
|
|
207
|
+
/** Server port */
|
|
208
|
+
readonly port: number;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Internal job representation from database
|
|
212
|
+
*/
|
|
213
|
+
interface ClaimedJob {
|
|
214
|
+
id: number;
|
|
215
|
+
public_id: string;
|
|
216
|
+
queue: string;
|
|
217
|
+
payload: string;
|
|
218
|
+
attempts: number;
|
|
219
|
+
max_attempts: number;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Create and initialize the workmatic database
|
|
224
|
+
*
|
|
225
|
+
* @param options - Database options
|
|
226
|
+
* @returns Kysely database instance
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* // Using a file path
|
|
231
|
+
* const db = createDatabase({ filename: './jobs.db' });
|
|
232
|
+
*
|
|
233
|
+
* // Using an existing better-sqlite3 instance
|
|
234
|
+
* import Database from 'better-sqlite3';
|
|
235
|
+
* const sqlite = new Database('./jobs.db');
|
|
236
|
+
* const db = createDatabase({ db: sqlite });
|
|
237
|
+
*
|
|
238
|
+
* // In-memory database (for testing)
|
|
239
|
+
* const db = createDatabase({ filename: ':memory:' });
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
declare function createDatabase(options?: DatabaseOptions): WorkmaticDb;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Create a job queue client for adding jobs
|
|
246
|
+
*
|
|
247
|
+
* @param options - Client options
|
|
248
|
+
* @returns Client instance
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* const client = createClient({ db });
|
|
253
|
+
*
|
|
254
|
+
* // Add a simple job
|
|
255
|
+
* const result = await client.add({ email: 'user@example.com' });
|
|
256
|
+
* console.log(result.id); // Job public ID
|
|
257
|
+
*
|
|
258
|
+
* // Add a job with options
|
|
259
|
+
* await client.add(
|
|
260
|
+
* { userId: 123 },
|
|
261
|
+
* { priority: 1, delayMs: 5000, maxAttempts: 5 }
|
|
262
|
+
* );
|
|
263
|
+
*
|
|
264
|
+
* // Get queue statistics
|
|
265
|
+
* const stats = await client.stats();
|
|
266
|
+
* console.log(stats); // { ready: 5, running: 2, done: 100, ... }
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
declare function createClient(options: ClientOptions): WorkmaticClient;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Create a job queue worker for processing jobs
|
|
273
|
+
*
|
|
274
|
+
* @param options - Worker options
|
|
275
|
+
* @returns Worker instance
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```ts
|
|
279
|
+
* const worker = createWorker({ db, concurrency: 4 });
|
|
280
|
+
*
|
|
281
|
+
* // Set the processor function
|
|
282
|
+
* worker.process(async (job) => {
|
|
283
|
+
* console.log('Processing job:', job.id);
|
|
284
|
+
* await sendEmail(job.payload.email);
|
|
285
|
+
* });
|
|
286
|
+
*
|
|
287
|
+
* // Start processing
|
|
288
|
+
* worker.start();
|
|
289
|
+
*
|
|
290
|
+
* // Later, gracefully stop
|
|
291
|
+
* await worker.stop();
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
declare function createWorker(options: WorkerOptions): WorkmaticWorker;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Create a dashboard HTTP server for monitoring and controlling the job queue
|
|
298
|
+
*
|
|
299
|
+
* @param options - Dashboard options
|
|
300
|
+
* @returns Dashboard instance
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* ```ts
|
|
304
|
+
* const dashboard = createDashboard({
|
|
305
|
+
* db,
|
|
306
|
+
* port: 3000,
|
|
307
|
+
* workers: [worker1, worker2]
|
|
308
|
+
* });
|
|
309
|
+
*
|
|
310
|
+
* console.log(`Dashboard running at http://localhost:${dashboard.port}`);
|
|
311
|
+
*
|
|
312
|
+
* // Later, close the server
|
|
313
|
+
* await dashboard.close();
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
declare function createDashboard(options: DashboardOptions): WorkmaticDashboard;
|
|
317
|
+
/**
|
|
318
|
+
* Create an Express-compatible middleware for the dashboard
|
|
319
|
+
*
|
|
320
|
+
* @param options - Middleware options
|
|
321
|
+
* @returns Express middleware function
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```ts
|
|
325
|
+
* import express from 'express';
|
|
326
|
+
* import { createDashboardMiddleware } from 'workmatic';
|
|
327
|
+
*
|
|
328
|
+
* const app = express();
|
|
329
|
+
*
|
|
330
|
+
* // Mount dashboard at /workmatic
|
|
331
|
+
* app.use(createDashboardMiddleware({
|
|
332
|
+
* db,
|
|
333
|
+
* basePath: '/workmatic',
|
|
334
|
+
* workers: [worker]
|
|
335
|
+
* }));
|
|
336
|
+
*
|
|
337
|
+
* app.listen(3000);
|
|
338
|
+
* // Dashboard available at http://localhost:3000/workmatic
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
declare function createDashboardMiddleware(options: DashboardMiddlewareOptions): DashboardMiddleware;
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Default exponential backoff function
|
|
345
|
+
* Returns delay in milliseconds: 1000 * 2^attempts
|
|
346
|
+
*
|
|
347
|
+
* @param attempts - Number of failed attempts
|
|
348
|
+
* @returns Delay in milliseconds
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```ts
|
|
352
|
+
* defaultBackoff(0) // 1000ms (1 second)
|
|
353
|
+
* defaultBackoff(1) // 2000ms (2 seconds)
|
|
354
|
+
* defaultBackoff(2) // 4000ms (4 seconds)
|
|
355
|
+
* defaultBackoff(3) // 8000ms (8 seconds)
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
declare const defaultBackoff: BackoffFunction;
|
|
359
|
+
/**
|
|
360
|
+
* Validate that a payload is JSON-serializable
|
|
3
361
|
*
|
|
4
|
-
* @
|
|
362
|
+
* @param payload - The payload to validate
|
|
363
|
+
* @throws Error if payload cannot be serialized to JSON
|
|
364
|
+
* @returns The JSON string representation
|
|
5
365
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export { createWorker
|
|
9
|
-
export { createDashboard, createDashboardMiddleware } from './dashboard.js';
|
|
10
|
-
export { defaultBackoff, validatePayload } from './utils.js';
|
|
11
|
-
export type { Job, JobStatus, JobStats, ClaimedJob, AddJobOptions, AddJobResult, DatabaseOptions, ClientOptions, WorkerOptions, DashboardOptions, DashboardMiddlewareOptions, BackoffFunction, JobProcessor, WorkmaticClient, WorkmaticWorker, WorkmaticDashboard, DashboardMiddleware, WorkmaticDb, WorkmaticDatabase, WorkmaticJobsTable, } from './types.js';
|
|
12
|
-
//# sourceMappingURL=index.d.ts.map
|
|
366
|
+
declare function validatePayload(payload: unknown): string;
|
|
367
|
+
|
|
368
|
+
export { type AddJobOptions, type AddJobResult, type BackoffFunction, type ClaimedJob, type ClientOptions, type DashboardMiddleware, type DashboardMiddlewareOptions, type DashboardOptions, type DatabaseOptions, type Job, type JobProcessor, type JobStats, type JobStatus, type WorkerOptions, type WorkmaticClient, type WorkmaticDashboard, type WorkmaticDatabase, type WorkmaticDb, type WorkmaticJobsTable, type WorkmaticWorker, createClient, createDashboard, createDashboardMiddleware, createDatabase, createWorker, defaultBackoff, validatePayload };
|