effect-mq 0.1.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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +235 -0
  3. package/dist/Job.d.ts +222 -0
  4. package/dist/Job.d.ts.map +1 -0
  5. package/dist/Job.js +218 -0
  6. package/dist/Job.js.map +1 -0
  7. package/dist/JobStore.d.ts +401 -0
  8. package/dist/JobStore.d.ts.map +1 -0
  9. package/dist/JobStore.js +89 -0
  10. package/dist/JobStore.js.map +1 -0
  11. package/dist/MemoryJobStore.d.ts +34 -0
  12. package/dist/MemoryJobStore.d.ts.map +1 -0
  13. package/dist/MemoryJobStore.js +381 -0
  14. package/dist/MemoryJobStore.js.map +1 -0
  15. package/dist/Worker.d.ts +127 -0
  16. package/dist/Worker.d.ts.map +1 -0
  17. package/dist/Worker.js +274 -0
  18. package/dist/Worker.js.map +1 -0
  19. package/dist/drizzle/DrizzleJobStore.d.ts +59 -0
  20. package/dist/drizzle/DrizzleJobStore.d.ts.map +1 -0
  21. package/dist/drizzle/DrizzleJobStore.js +426 -0
  22. package/dist/drizzle/DrizzleJobStore.js.map +1 -0
  23. package/dist/drizzle/index.d.ts +19 -0
  24. package/dist/drizzle/index.d.ts.map +1 -0
  25. package/dist/drizzle/index.js +19 -0
  26. package/dist/drizzle/index.js.map +1 -0
  27. package/dist/drizzle/schema.d.ts +464 -0
  28. package/dist/drizzle/schema.d.ts.map +1 -0
  29. package/dist/drizzle/schema.js +68 -0
  30. package/dist/drizzle/schema.js.map +1 -0
  31. package/dist/index.d.ts +30 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +30 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/testing/conformance.d.ts +27 -0
  36. package/dist/testing/conformance.d.ts.map +1 -0
  37. package/dist/testing/conformance.js +451 -0
  38. package/dist/testing/conformance.js.map +1 -0
  39. package/dist/testing/index.d.ts +8 -0
  40. package/dist/testing/index.d.ts.map +1 -0
  41. package/dist/testing/index.js +8 -0
  42. package/dist/testing/index.js.map +1 -0
  43. package/package.json +71 -0
  44. package/src/Job.ts +606 -0
  45. package/src/JobStore.ts +446 -0
  46. package/src/MemoryJobStore.ts +467 -0
  47. package/src/Worker.ts +514 -0
  48. package/src/drizzle/DrizzleJobStore.ts +599 -0
  49. package/src/drizzle/index.ts +20 -0
  50. package/src/drizzle/schema.ts +116 -0
  51. package/src/index.ts +33 -0
  52. package/src/testing/conformance.ts +654 -0
  53. package/src/testing/index.ts +7 -0
@@ -0,0 +1,464 @@
1
+ /**
2
+ * Drizzle schema factories for effect-mq's Postgres tables.
3
+ *
4
+ * Re-export these from your own drizzle schema so drizzle-kit owns the
5
+ * migrations and your queries are fully typed — including the job `name`
6
+ * column typed to the union of your job tags:
7
+ *
8
+ * ```ts
9
+ * // schema.ts
10
+ * import { mqJobAttempts, mqJobs } from "effect-mq/drizzle"
11
+ *
12
+ * type DurableJobs = typeof SyncBenefits._tag | typeof GenerateReport._tag
13
+ * export const jobs = mqJobs<DurableJobs>()
14
+ * export const jobAttempts = mqJobAttempts(jobs)
15
+ * ```
16
+ *
17
+ * Then `drizzle-kit generate` emits the CREATE TABLE migrations into your
18
+ * pipeline like any other table. Reads through drizzle are encouraged;
19
+ * writes must go through the `JobStore` (e.g. `store.retry`) so locking and
20
+ * wake-up invariants hold.
21
+ *
22
+ * @since 0.1.0
23
+ */
24
+ import type * as JobStore from "../JobStore.ts";
25
+ /**
26
+ * The jobs table factory. `JobName` types the `name` column — derive it from
27
+ * your job definitions: `mqJobs<typeof SyncBenefits._tag | typeof Report._tag>()`.
28
+ *
29
+ * @since 0.1.0
30
+ */
31
+ export declare const mqJobs: <JobName extends string = string>(tableName?: string) => import("drizzle-orm/pg-core").PgTableWithColumns<{
32
+ name: string;
33
+ schema: undefined;
34
+ columns: {
35
+ id: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetIsPrimaryKey<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, JobStore.JobId>, {
36
+ name: string;
37
+ tableName: string;
38
+ dataType: "string";
39
+ data: JobStore.JobId;
40
+ driverParam: string;
41
+ notNull: true;
42
+ hasDefault: false;
43
+ isPrimaryKey: false;
44
+ isAutoincrement: false;
45
+ hasRuntimeDefault: false;
46
+ enumValues: undefined;
47
+ identity: undefined;
48
+ generated: undefined;
49
+ }>;
50
+ name: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, JobName>, {
51
+ name: string;
52
+ tableName: string;
53
+ dataType: "string";
54
+ data: JobName;
55
+ driverParam: string;
56
+ notNull: true;
57
+ hasDefault: false;
58
+ isPrimaryKey: false;
59
+ isAutoincrement: false;
60
+ hasRuntimeDefault: false;
61
+ enumValues: undefined;
62
+ identity: undefined;
63
+ generated: undefined;
64
+ }>;
65
+ queue: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, JobStore.QueueName>, {
66
+ name: string;
67
+ tableName: string;
68
+ dataType: "string";
69
+ data: JobStore.QueueName;
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: false;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: undefined;
77
+ identity: undefined;
78
+ generated: undefined;
79
+ }>;
80
+ state: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, JobStore.JobState>, {
81
+ name: string;
82
+ tableName: string;
83
+ dataType: "string";
84
+ data: JobStore.JobState;
85
+ driverParam: string;
86
+ notNull: true;
87
+ hasDefault: false;
88
+ isPrimaryKey: false;
89
+ isAutoincrement: false;
90
+ hasRuntimeDefault: false;
91
+ enumValues: undefined;
92
+ identity: undefined;
93
+ generated: undefined;
94
+ }>;
95
+ priority: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetHasDefault<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgIntegerBuilder>>, {
96
+ name: string;
97
+ tableName: string;
98
+ dataType: "number int32";
99
+ data: number;
100
+ driverParam: string | number;
101
+ notNull: true;
102
+ hasDefault: true;
103
+ isPrimaryKey: false;
104
+ isAutoincrement: false;
105
+ hasRuntimeDefault: false;
106
+ enumValues: undefined;
107
+ identity: undefined;
108
+ generated: undefined;
109
+ }>;
110
+ seq: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").HasIdentity<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgBigInt53Builder>, "byDefault">, {
111
+ name: string;
112
+ tableName: string;
113
+ dataType: "number int53";
114
+ data: number;
115
+ driverParam: string | number;
116
+ notNull: true;
117
+ hasDefault: true;
118
+ isPrimaryKey: false;
119
+ isAutoincrement: false;
120
+ hasRuntimeDefault: false;
121
+ enumValues: undefined;
122
+ identity: "byDefault";
123
+ generated: undefined;
124
+ }>;
125
+ payload: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgJsonbBuilder, {
126
+ name: string;
127
+ tableName: string;
128
+ dataType: "object json";
129
+ data: unknown;
130
+ driverParam: unknown;
131
+ notNull: false;
132
+ hasDefault: false;
133
+ isPrimaryKey: false;
134
+ isAutoincrement: false;
135
+ hasRuntimeDefault: false;
136
+ enumValues: undefined;
137
+ identity: undefined;
138
+ generated: undefined;
139
+ }>;
140
+ metadata: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetHasDefault<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgJsonbBuilder>>, Record<string, string>>, {
141
+ name: string;
142
+ tableName: string;
143
+ dataType: "object json";
144
+ data: Record<string, string>;
145
+ driverParam: unknown;
146
+ notNull: true;
147
+ hasDefault: true;
148
+ isPrimaryKey: false;
149
+ isAutoincrement: false;
150
+ hasRuntimeDefault: false;
151
+ enumValues: undefined;
152
+ identity: undefined;
153
+ generated: undefined;
154
+ }>;
155
+ attemptsMax: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgIntegerBuilder>, {
156
+ name: string;
157
+ tableName: string;
158
+ dataType: "number int32";
159
+ data: number;
160
+ driverParam: string | number;
161
+ notNull: true;
162
+ hasDefault: false;
163
+ isPrimaryKey: false;
164
+ isAutoincrement: false;
165
+ hasRuntimeDefault: false;
166
+ enumValues: undefined;
167
+ identity: undefined;
168
+ generated: undefined;
169
+ }>;
170
+ attemptsMade: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetHasDefault<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgIntegerBuilder>>, {
171
+ name: string;
172
+ tableName: string;
173
+ dataType: "number int32";
174
+ data: number;
175
+ driverParam: string | number;
176
+ notNull: true;
177
+ hasDefault: true;
178
+ isPrimaryKey: false;
179
+ isAutoincrement: false;
180
+ hasRuntimeDefault: false;
181
+ enumValues: undefined;
182
+ identity: undefined;
183
+ generated: undefined;
184
+ }>;
185
+ stalledCount: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetHasDefault<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgIntegerBuilder>>, {
186
+ name: string;
187
+ tableName: string;
188
+ dataType: "number int32";
189
+ data: number;
190
+ driverParam: string | number;
191
+ notNull: true;
192
+ hasDefault: true;
193
+ isPrimaryKey: false;
194
+ isAutoincrement: false;
195
+ hasRuntimeDefault: false;
196
+ enumValues: undefined;
197
+ identity: undefined;
198
+ generated: undefined;
199
+ }>;
200
+ backoff: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").PgJsonbBuilder, JobStore.BackoffPolicy>, {
201
+ name: string;
202
+ tableName: string;
203
+ dataType: "object json";
204
+ data: JobStore.BackoffPolicy;
205
+ driverParam: unknown;
206
+ notNull: false;
207
+ hasDefault: false;
208
+ isPrimaryKey: false;
209
+ isAutoincrement: false;
210
+ hasRuntimeDefault: false;
211
+ enumValues: undefined;
212
+ identity: undefined;
213
+ generated: undefined;
214
+ }>;
215
+ keep: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").PgJsonbBuilder, JobStore.KeepPolicy>, {
216
+ name: string;
217
+ tableName: string;
218
+ dataType: "object json";
219
+ data: JobStore.KeepPolicy;
220
+ driverParam: unknown;
221
+ notNull: false;
222
+ hasDefault: false;
223
+ isPrimaryKey: false;
224
+ isAutoincrement: false;
225
+ hasRuntimeDefault: false;
226
+ enumValues: undefined;
227
+ identity: undefined;
228
+ generated: undefined;
229
+ }>;
230
+ runAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTimestampBuilder>, {
231
+ name: string;
232
+ tableName: string;
233
+ dataType: "object date";
234
+ data: Date;
235
+ driverParam: string;
236
+ notNull: true;
237
+ hasDefault: false;
238
+ isPrimaryKey: false;
239
+ isAutoincrement: false;
240
+ hasRuntimeDefault: false;
241
+ enumValues: undefined;
242
+ identity: undefined;
243
+ generated: undefined;
244
+ }>;
245
+ enqueuedAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTimestampBuilder>, {
246
+ name: string;
247
+ tableName: string;
248
+ dataType: "object date";
249
+ data: Date;
250
+ driverParam: string;
251
+ notNull: true;
252
+ hasDefault: false;
253
+ isPrimaryKey: false;
254
+ isAutoincrement: false;
255
+ hasRuntimeDefault: false;
256
+ enumValues: undefined;
257
+ identity: undefined;
258
+ generated: undefined;
259
+ }>;
260
+ processedAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
261
+ name: string;
262
+ tableName: string;
263
+ dataType: "object date";
264
+ data: Date;
265
+ driverParam: string;
266
+ notNull: false;
267
+ hasDefault: false;
268
+ isPrimaryKey: false;
269
+ isAutoincrement: false;
270
+ hasRuntimeDefault: false;
271
+ enumValues: undefined;
272
+ identity: undefined;
273
+ generated: undefined;
274
+ }>;
275
+ finishedAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
276
+ name: string;
277
+ tableName: string;
278
+ dataType: "object date";
279
+ data: Date;
280
+ driverParam: string;
281
+ notNull: false;
282
+ hasDefault: false;
283
+ isPrimaryKey: false;
284
+ isAutoincrement: false;
285
+ hasRuntimeDefault: false;
286
+ enumValues: undefined;
287
+ identity: undefined;
288
+ generated: undefined;
289
+ }>;
290
+ exit: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgJsonbBuilder, {
291
+ name: string;
292
+ tableName: string;
293
+ dataType: "object json";
294
+ data: unknown;
295
+ driverParam: unknown;
296
+ notNull: false;
297
+ hasDefault: false;
298
+ isPrimaryKey: false;
299
+ isAutoincrement: false;
300
+ hasRuntimeDefault: false;
301
+ enumValues: undefined;
302
+ identity: undefined;
303
+ generated: undefined;
304
+ }>;
305
+ failedReason: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>, {
306
+ name: string;
307
+ tableName: string;
308
+ dataType: "string";
309
+ data: string;
310
+ driverParam: string;
311
+ notNull: false;
312
+ hasDefault: false;
313
+ isPrimaryKey: false;
314
+ isAutoincrement: false;
315
+ hasRuntimeDefault: false;
316
+ enumValues: undefined;
317
+ identity: undefined;
318
+ generated: undefined;
319
+ }>;
320
+ lockToken: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>, {
321
+ name: string;
322
+ tableName: string;
323
+ dataType: "string";
324
+ data: string;
325
+ driverParam: string;
326
+ notNull: false;
327
+ hasDefault: false;
328
+ isPrimaryKey: false;
329
+ isAutoincrement: false;
330
+ hasRuntimeDefault: false;
331
+ enumValues: undefined;
332
+ identity: undefined;
333
+ generated: undefined;
334
+ }>;
335
+ lockExpiresAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
336
+ name: string;
337
+ tableName: string;
338
+ dataType: "object date";
339
+ data: Date;
340
+ driverParam: string;
341
+ notNull: false;
342
+ hasDefault: false;
343
+ isPrimaryKey: false;
344
+ isAutoincrement: false;
345
+ hasRuntimeDefault: false;
346
+ enumValues: undefined;
347
+ identity: undefined;
348
+ generated: undefined;
349
+ }>;
350
+ };
351
+ dialect: 'pg';
352
+ }>;
353
+ /**
354
+ * The job run-ledger table factory (one row per attempt, including
355
+ * successes and stall recoveries).
356
+ *
357
+ * @since 0.1.0
358
+ */
359
+ export declare const mqJobAttempts: (jobs: ReturnType<typeof mqJobs<any>>, tableName?: string) => import("drizzle-orm/pg-core").PgTableWithColumns<{
360
+ name: string;
361
+ schema: undefined;
362
+ columns: {
363
+ jobId: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, JobStore.JobId>, {
364
+ name: string;
365
+ tableName: string;
366
+ dataType: "string";
367
+ data: JobStore.JobId;
368
+ driverParam: string;
369
+ notNull: true;
370
+ hasDefault: false;
371
+ isPrimaryKey: false;
372
+ isAutoincrement: false;
373
+ hasRuntimeDefault: false;
374
+ enumValues: undefined;
375
+ identity: undefined;
376
+ generated: undefined;
377
+ }>;
378
+ attempt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgIntegerBuilder>, {
379
+ name: string;
380
+ tableName: string;
381
+ dataType: "number int32";
382
+ data: number;
383
+ driverParam: string | number;
384
+ notNull: true;
385
+ hasDefault: false;
386
+ isPrimaryKey: false;
387
+ isAutoincrement: false;
388
+ hasRuntimeDefault: false;
389
+ enumValues: undefined;
390
+ identity: undefined;
391
+ generated: undefined;
392
+ }>;
393
+ outcome: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, "completed" | "failed" | "retried" | "stalled">, {
394
+ name: string;
395
+ tableName: string;
396
+ dataType: "string";
397
+ data: "completed" | "failed" | "retried" | "stalled";
398
+ driverParam: string;
399
+ notNull: true;
400
+ hasDefault: false;
401
+ isPrimaryKey: false;
402
+ isAutoincrement: false;
403
+ hasRuntimeDefault: false;
404
+ enumValues: undefined;
405
+ identity: undefined;
406
+ generated: undefined;
407
+ }>;
408
+ startedAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
409
+ name: string;
410
+ tableName: string;
411
+ dataType: "object date";
412
+ data: Date;
413
+ driverParam: string;
414
+ notNull: false;
415
+ hasDefault: false;
416
+ isPrimaryKey: false;
417
+ isAutoincrement: false;
418
+ hasRuntimeDefault: false;
419
+ enumValues: undefined;
420
+ identity: undefined;
421
+ generated: undefined;
422
+ }>;
423
+ finishedAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTimestampBuilder>, {
424
+ name: string;
425
+ tableName: string;
426
+ dataType: "object date";
427
+ data: Date;
428
+ driverParam: string;
429
+ notNull: true;
430
+ hasDefault: false;
431
+ isPrimaryKey: false;
432
+ isAutoincrement: false;
433
+ hasRuntimeDefault: false;
434
+ enumValues: undefined;
435
+ identity: undefined;
436
+ generated: undefined;
437
+ }>;
438
+ exit: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgJsonbBuilder, {
439
+ name: string;
440
+ tableName: string;
441
+ dataType: "object json";
442
+ data: unknown;
443
+ driverParam: unknown;
444
+ notNull: false;
445
+ hasDefault: false;
446
+ isPrimaryKey: false;
447
+ isAutoincrement: false;
448
+ hasRuntimeDefault: false;
449
+ enumValues: undefined;
450
+ identity: undefined;
451
+ generated: undefined;
452
+ }>;
453
+ };
454
+ dialect: 'pg';
455
+ }>;
456
+ /**
457
+ * @since 0.1.0
458
+ */
459
+ export type MqJobsTable = ReturnType<typeof mqJobs<any>>;
460
+ /**
461
+ * @since 0.1.0
462
+ */
463
+ export type MqJobAttemptsTable = ReturnType<typeof mqJobAttempts>;
464
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/drizzle/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAU/C;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,OAAO,SAAS,MAAM,GAAG,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6ClD,CAAA;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAClB,UAAU,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYlC,CAAA;AAEJ;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;AAExD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA"}
@@ -0,0 +1,68 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { bigint, index, integer, jsonb, pgTable, primaryKey, text, timestamp } from "drizzle-orm/pg-core";
3
+ /**
4
+ * The jobs table factory. `JobName` types the `name` column — derive it from
5
+ * your job definitions: `mqJobs<typeof SyncBenefits._tag | typeof Report._tag>()`.
6
+ *
7
+ * @since 0.1.0
8
+ */
9
+ export const mqJobs = (tableName = "effect_mq_jobs") => pgTable(tableName, {
10
+ id: text("id").primaryKey().$type(),
11
+ name: text("name").notNull().$type(),
12
+ queue: text("queue").notNull().$type(),
13
+ state: text("state").notNull().$type(),
14
+ priority: integer("priority").notNull().default(0),
15
+ /** FIFO order within a priority; bumped on retry so retries go to the tail. */
16
+ seq: bigint("seq", { mode: "number" }).notNull().generatedByDefaultAsIdentity(),
17
+ payload: jsonb("payload"),
18
+ metadata: jsonb("metadata").notNull().default({}).$type(),
19
+ attemptsMax: integer("attempts_max").notNull(),
20
+ attemptsMade: integer("attempts_made").notNull().default(0),
21
+ stalledCount: integer("stalled_count").notNull().default(0),
22
+ backoff: jsonb("backoff").$type(),
23
+ keep: jsonb("keep").$type(),
24
+ runAt: timestamp("run_at", { withTimezone: true, mode: "date" }).notNull(),
25
+ enqueuedAt: timestamp("enqueued_at", { withTimezone: true, mode: "date" }).notNull(),
26
+ processedAt: timestamp("processed_at", { withTimezone: true, mode: "date" }),
27
+ finishedAt: timestamp("finished_at", { withTimezone: true, mode: "date" }),
28
+ exit: jsonb("exit"),
29
+ failedReason: text("failed_reason"),
30
+ lockToken: text("lock_token"),
31
+ lockExpiresAt: timestamp("lock_expires_at", { withTimezone: true, mode: "date" })
32
+ }, (table) => [
33
+ // Claim path: pop highest priority, FIFO within it.
34
+ index(`${tableName}_ready_idx`)
35
+ .on(table.queue, table.priority.desc(), table.seq.asc())
36
+ .where(sql `${table.state} = 'waiting'`),
37
+ // Delayed promotion + nextRunAt.
38
+ index(`${tableName}_delayed_idx`)
39
+ .on(table.queue, table.runAt)
40
+ .where(sql `${table.state} = 'delayed'`),
41
+ // Stalled sweep.
42
+ index(`${tableName}_active_idx`)
43
+ .on(table.lockExpiresAt)
44
+ .where(sql `${table.state} = 'active'`),
45
+ // History/retention queries.
46
+ index(`${tableName}_history_idx`).on(table.name, table.state, table.finishedAt),
47
+ // Listing (newest first, keyset pagination).
48
+ index(`${tableName}_listing_idx`).on(table.enqueuedAt.desc(), table.id.desc()),
49
+ // Metadata containment queries.
50
+ index(`${tableName}_metadata_idx`).using("gin", table.metadata.op("jsonb_path_ops"))
51
+ ]);
52
+ /**
53
+ * The job run-ledger table factory (one row per attempt, including
54
+ * successes and stall recoveries).
55
+ *
56
+ * @since 0.1.0
57
+ */
58
+ export const mqJobAttempts = (jobs, tableName = "effect_mq_job_attempts") => pgTable(tableName, {
59
+ jobId: text("job_id").notNull().references(() => jobs.id, { onDelete: "cascade" }).$type(),
60
+ attempt: integer("attempt").notNull(),
61
+ outcome: text("outcome").notNull().$type(),
62
+ startedAt: timestamp("started_at", { withTimezone: true, mode: "date" }),
63
+ finishedAt: timestamp("finished_at", { withTimezone: true, mode: "date" }).notNull(),
64
+ exit: jsonb("exit")
65
+ }, (table) => [
66
+ primaryKey({ columns: [table.jobId, table.attempt] })
67
+ ]);
68
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/drizzle/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Effect-native, storage-agnostic background jobs.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+ /**
7
+ * Schema-first job definitions: `Job.make`, `enqueue`, `toLayer`.
8
+ *
9
+ * @since 0.1.0
10
+ */
11
+ export * as Job from "./Job.ts";
12
+ /**
13
+ * The storage seam: the `JobStore` service, job records and typed errors.
14
+ *
15
+ * @since 0.1.0
16
+ */
17
+ export * as JobStore from "./JobStore.ts";
18
+ /**
19
+ * The reference in-memory `JobStore` driver (Effect primitives only).
20
+ *
21
+ * @since 0.1.0
22
+ */
23
+ export * as MemoryJobStore from "./MemoryJobStore.ts";
24
+ /**
25
+ * The worker runtime: `Worker.layer` and handler registration.
26
+ *
27
+ * @since 0.1.0
28
+ */
29
+ export * as Worker from "./Worker.ts";
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAE/B;;;;GAIG;AACH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC;;;;GAIG;AACH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Effect-native, storage-agnostic background jobs.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+ /**
7
+ * Schema-first job definitions: `Job.make`, `enqueue`, `toLayer`.
8
+ *
9
+ * @since 0.1.0
10
+ */
11
+ export * as Job from "./Job.js";
12
+ /**
13
+ * The storage seam: the `JobStore` service, job records and typed errors.
14
+ *
15
+ * @since 0.1.0
16
+ */
17
+ export * as JobStore from "./JobStore.js";
18
+ /**
19
+ * The reference in-memory `JobStore` driver (Effect primitives only).
20
+ *
21
+ * @since 0.1.0
22
+ */
23
+ export * as MemoryJobStore from "./MemoryJobStore.js";
24
+ /**
25
+ * The worker runtime: `Worker.layer` and handler registration.
26
+ *
27
+ * @since 0.1.0
28
+ */
29
+ export * as Worker from "./Worker.js";
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAE/B;;;;GAIG;AACH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC;;;;GAIG;AACH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Conformance suite for `JobStore` implementations.
3
+ *
4
+ * Every storage driver must pass this suite. Run it from a vitest file:
5
+ *
6
+ * ```ts
7
+ * import { jobStoreConformance } from "effect-mq/testing"
8
+ * import { MemoryJobStore } from "effect-mq"
9
+ *
10
+ * jobStoreConformance("MemoryJobStore", () => MemoryJobStore.layer)
11
+ * ```
12
+ *
13
+ * The suite runs under `TestClock`. Drivers must derive ALL time from the
14
+ * Effect `Clock` (e.g. pass `now` into queries as a bind parameter) — never
15
+ * from the database server's clock — so this works against real storage too.
16
+ *
17
+ * @since 0.1.0
18
+ */
19
+ import * as JobStore from "../JobStore.ts";
20
+ import { type Layer } from "effect";
21
+ /**
22
+ * Assert a `JobStore` implementation behaves according to the contract.
23
+ *
24
+ * @since 0.1.0
25
+ */
26
+ export declare const jobStoreConformance: (name: string, storeLayer: () => Layer.Layer<JobStore.JobStore>) => void;
27
+ //# sourceMappingURL=conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/testing/conformance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAE1C,OAAO,EAAuB,KAAK,KAAK,EAAU,MAAM,QAAQ,CAAA;AA+BhE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,SACxB,MAAM,cACA,MAAM,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAC/C,IAklBF,CAAA"}