@pattern-stack/codegen 0.22.0 → 0.23.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 (48) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/{chunk-NR7QQ6ZI.js → chunk-42763UEE.js} +2 -2
  3. package/dist/{chunk-6ECCJVYW.js → chunk-4M66MQYA.js} +44 -2
  4. package/dist/chunk-4M66MQYA.js.map +1 -0
  5. package/dist/{chunk-FNHNSFIJ.js → chunk-6XP2Q5SS.js} +2 -2
  6. package/dist/{chunk-VDL5CJ5C.js → chunk-7B7MMDOJ.js} +54 -1
  7. package/dist/chunk-7B7MMDOJ.js.map +1 -0
  8. package/dist/{chunk-NXHL5YII.js → chunk-7LKAMLV4.js} +4 -4
  9. package/dist/{chunk-6DQEIXYU.js → chunk-FIUC6QB5.js} +1 -1
  10. package/dist/chunk-FIUC6QB5.js.map +1 -0
  11. package/dist/{chunk-DB5UXJC3.js → chunk-PNCOUFFI.js} +4 -2
  12. package/dist/chunk-PNCOUFFI.js.map +1 -0
  13. package/dist/{chunk-QXVCRA23.js → chunk-SH76CFAY.js} +9 -4
  14. package/dist/chunk-SH76CFAY.js.map +1 -0
  15. package/dist/runtime/base-classes/index.js +17 -17
  16. package/dist/runtime/subsystems/auth/auth.module.js +3 -3
  17. package/dist/runtime/subsystems/auth/index.js +7 -7
  18. package/dist/runtime/subsystems/bridge/bridge.module.js +4 -4
  19. package/dist/runtime/subsystems/bridge/index.js +4 -4
  20. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +1 -1
  21. package/dist/runtime/subsystems/events/events.module.js +2 -2
  22. package/dist/runtime/subsystems/events/index.js +2 -2
  23. package/dist/runtime/subsystems/index.js +12 -12
  24. package/dist/runtime/subsystems/jobs/index.js +3 -3
  25. package/dist/runtime/subsystems/jobs/job-worker.d.ts +592 -4
  26. package/dist/runtime/subsystems/jobs/job-worker.js +3 -1
  27. package/dist/runtime/subsystems/jobs/job-worker.module.js +3 -3
  28. package/dist/runtime/subsystems/jobs/jobs-domain.module.d.ts +19 -0
  29. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +1 -1
  30. package/dist/src/cli/index.js +211 -60
  31. package/dist/src/cli/index.js.map +1 -1
  32. package/dist/src/index.d.ts +477 -1
  33. package/dist/src/index.js +1 -1
  34. package/package.json +1 -1
  35. package/runtime/subsystems/events/event-bus.drizzle-backend.ts +23 -7
  36. package/runtime/subsystems/jobs/job-worker.module.ts +5 -0
  37. package/runtime/subsystems/jobs/job-worker.ts +126 -12
  38. package/runtime/subsystems/jobs/jobs-domain.module.ts +19 -0
  39. package/templates/entity/new/clean-lite-ps/prompt-extension.js +59 -10
  40. package/templates/subsystem/jobs-config/codegen-config-jobs-block.ejs.t +11 -0
  41. package/dist/chunk-6DQEIXYU.js.map +0 -1
  42. package/dist/chunk-6ECCJVYW.js.map +0 -1
  43. package/dist/chunk-DB5UXJC3.js.map +0 -1
  44. package/dist/chunk-QXVCRA23.js.map +0 -1
  45. package/dist/chunk-VDL5CJ5C.js.map +0 -1
  46. /package/dist/{chunk-NR7QQ6ZI.js.map → chunk-42763UEE.js.map} +0 -0
  47. /package/dist/{chunk-FNHNSFIJ.js.map → chunk-6XP2Q5SS.js.map} +0 -0
  48. /package/dist/{chunk-NXHL5YII.js.map → chunk-7LKAMLV4.js.map} +0 -0
@@ -1,3 +1,4 @@
1
+ import * as drizzle_orm_node_postgres from 'drizzle-orm/node-postgres';
1
2
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
3
  import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
3
4
  import { ModuleRef } from '@nestjs/core';
@@ -6,7 +7,6 @@ import { JobRunRow } from './job-orchestration.schema.js';
6
7
  import { I as IJobOrchestrator, R as RetryPolicy } from '../../../job-orchestrator.protocol-ZuJ3ow-O.js';
7
8
  import { IJobRunService } from './job-run-service.protocol.js';
8
9
  import { IJobStepService } from './job-step-service.protocol.js';
9
- import 'drizzle-orm/node-postgres';
10
10
  import 'drizzle-orm';
11
11
  import '../events/event-bus.protocol.js';
12
12
  import '../events/event-registry.js';
@@ -26,10 +26,29 @@ interface JobWorkerOptions {
26
26
  /** Stale sweep interval in ms. Default 60_000. */
27
27
  staleSweeperIntervalMs?: number;
28
28
  /**
29
- * Threshold beyond which a `running` row is presumed stranded by a
30
- * crashed worker. Default 5 min. Must be >= max handler duration.
29
+ * Threshold beyond which a `running` row whose `claimed_at` has NOT been
30
+ * renewed is presumed stranded by a crashed worker, and the sweeper resets
31
+ * it to `pending`. Default 5 min.
32
+ *
33
+ * With the claim heartbeat (CLAIM-HB-1) in place this is a *liveness*
34
+ * threshold — a live worker bumps `claimed_at` every
35
+ * `claimHeartbeatIntervalMs`, so a long-running-but-alive handler is NEVER
36
+ * swept; only a row whose worker died (process crash/SIGKILL, no clean
37
+ * shutdown reset) ages past the threshold. It therefore no longer needs to
38
+ * be `>= 2× max handler duration` — it just needs to exceed a few missed
39
+ * heartbeats (default leaves a 3× heartbeat margin).
31
40
  */
32
41
  staleThresholdMs?: number;
42
+ /**
43
+ * CLAIM-HB-1 — interval at which this worker bumps `claimed_at = now()` for
44
+ * every run it currently holds in flight (one batched UPDATE). This is the
45
+ * lease renewal that keeps a legitimately long-running handler from being
46
+ * swept by `sweepStaleClaims`. Default `staleThresholdMs / 3` so a row
47
+ * survives up to two missed renewals before the sweeper acts. MUST be
48
+ * comfortably less than `staleThresholdMs` or live runs will be re-queued
49
+ * mid-flight.
50
+ */
51
+ claimHeartbeatIntervalMs?: number;
33
52
  /** Max ms to wait for in-flight drain on SIGTERM. Default 30_000. */
34
53
  shutdownTimeoutMs?: number;
35
54
  /**
@@ -144,6 +163,550 @@ declare function buildStaleSweepQuery(db: DrizzleClient, staleThresholdMs: numbe
144
163
  generated: undefined;
145
164
  }, {}, {}>;
146
165
  }>, "where" | "for">;
166
+ /**
167
+ * CLAIM-HB-1 — build the heartbeat renewal UPDATE. Bumps `claimed_at = now()`
168
+ * (and `updated_at`) for the given run IDs, but ONLY rows still `status =
169
+ * 'running'`: a row this worker thinks it owns may have been swept and
170
+ * reclaimed by another worker (now running elsewhere), or already moved to a
171
+ * terminal state — the status guard makes the renewal a safe no-op in both
172
+ * cases rather than resurrecting a lease the worker no longer holds. Exported so
173
+ * tests can inspect `.toSQL()` without a live DB.
174
+ */
175
+ declare function buildClaimRenewQuery(db: DrizzleClient, runIds: string[], now?: Date): Omit<drizzle_orm_pg_core.PgUpdateBase<drizzle_orm_pg_core.PgTableWithColumns<{
176
+ name: "job_run";
177
+ schema: undefined;
178
+ columns: {
179
+ id: drizzle_orm_pg_core.PgColumn<{
180
+ name: "id";
181
+ tableName: "job_run";
182
+ dataType: "string";
183
+ columnType: "PgUUID";
184
+ data: string;
185
+ driverParam: string;
186
+ notNull: true;
187
+ hasDefault: true;
188
+ isPrimaryKey: true;
189
+ isAutoincrement: false;
190
+ hasRuntimeDefault: false;
191
+ enumValues: undefined;
192
+ baseColumn: never;
193
+ identity: undefined;
194
+ generated: undefined;
195
+ }, {}, {}>;
196
+ jobType: drizzle_orm_pg_core.PgColumn<{
197
+ name: "job_type";
198
+ tableName: "job_run";
199
+ dataType: "string";
200
+ columnType: "PgText";
201
+ data: string;
202
+ driverParam: string;
203
+ notNull: true;
204
+ hasDefault: false;
205
+ isPrimaryKey: false;
206
+ isAutoincrement: false;
207
+ hasRuntimeDefault: false;
208
+ enumValues: [string, ...string[]];
209
+ baseColumn: never;
210
+ identity: undefined;
211
+ generated: undefined;
212
+ }, {}, {}>;
213
+ jobVersion: drizzle_orm_pg_core.PgColumn<{
214
+ name: "job_version";
215
+ tableName: "job_run";
216
+ dataType: "number";
217
+ columnType: "PgInteger";
218
+ data: number;
219
+ driverParam: string | number;
220
+ notNull: true;
221
+ hasDefault: false;
222
+ isPrimaryKey: false;
223
+ isAutoincrement: false;
224
+ hasRuntimeDefault: false;
225
+ enumValues: undefined;
226
+ baseColumn: never;
227
+ identity: undefined;
228
+ generated: undefined;
229
+ }, {}, {}>;
230
+ parentRunId: drizzle_orm_pg_core.PgColumn<{
231
+ name: "parent_run_id";
232
+ tableName: "job_run";
233
+ dataType: "string";
234
+ columnType: "PgUUID";
235
+ data: string;
236
+ driverParam: string;
237
+ notNull: false;
238
+ hasDefault: false;
239
+ isPrimaryKey: false;
240
+ isAutoincrement: false;
241
+ hasRuntimeDefault: false;
242
+ enumValues: undefined;
243
+ baseColumn: never;
244
+ identity: undefined;
245
+ generated: undefined;
246
+ }, {}, {}>;
247
+ rootRunId: drizzle_orm_pg_core.PgColumn<{
248
+ name: "root_run_id";
249
+ tableName: "job_run";
250
+ dataType: "string";
251
+ columnType: "PgUUID";
252
+ data: string;
253
+ driverParam: string;
254
+ notNull: true;
255
+ hasDefault: false;
256
+ isPrimaryKey: false;
257
+ isAutoincrement: false;
258
+ hasRuntimeDefault: false;
259
+ enumValues: undefined;
260
+ baseColumn: never;
261
+ identity: undefined;
262
+ generated: undefined;
263
+ }, {}, {}>;
264
+ parentClosePolicy: drizzle_orm_pg_core.PgColumn<{
265
+ name: "parent_close_policy";
266
+ tableName: "job_run";
267
+ dataType: "string";
268
+ columnType: "PgEnumColumn";
269
+ data: "terminate" | "cancel" | "abandon";
270
+ driverParam: string;
271
+ notNull: true;
272
+ hasDefault: true;
273
+ isPrimaryKey: false;
274
+ isAutoincrement: false;
275
+ hasRuntimeDefault: false;
276
+ enumValues: ["terminate", "cancel", "abandon"];
277
+ baseColumn: never;
278
+ identity: undefined;
279
+ generated: undefined;
280
+ }, {}, {}>;
281
+ scopeEntityType: drizzle_orm_pg_core.PgColumn<{
282
+ name: "scope_entity_type";
283
+ tableName: "job_run";
284
+ dataType: "string";
285
+ columnType: "PgText";
286
+ data: string;
287
+ driverParam: string;
288
+ notNull: false;
289
+ hasDefault: false;
290
+ isPrimaryKey: false;
291
+ isAutoincrement: false;
292
+ hasRuntimeDefault: false;
293
+ enumValues: [string, ...string[]];
294
+ baseColumn: never;
295
+ identity: undefined;
296
+ generated: undefined;
297
+ }, {}, {}>;
298
+ scopeEntityId: drizzle_orm_pg_core.PgColumn<{
299
+ name: "scope_entity_id";
300
+ tableName: "job_run";
301
+ dataType: "string";
302
+ columnType: "PgText";
303
+ data: string;
304
+ driverParam: string;
305
+ notNull: false;
306
+ hasDefault: false;
307
+ isPrimaryKey: false;
308
+ isAutoincrement: false;
309
+ hasRuntimeDefault: false;
310
+ enumValues: [string, ...string[]];
311
+ baseColumn: never;
312
+ identity: undefined;
313
+ generated: undefined;
314
+ }, {}, {}>;
315
+ tenantId: drizzle_orm_pg_core.PgColumn<{
316
+ name: "tenant_id";
317
+ tableName: "job_run";
318
+ dataType: "string";
319
+ columnType: "PgText";
320
+ data: string;
321
+ driverParam: string;
322
+ notNull: false;
323
+ hasDefault: false;
324
+ isPrimaryKey: false;
325
+ isAutoincrement: false;
326
+ hasRuntimeDefault: false;
327
+ enumValues: [string, ...string[]];
328
+ baseColumn: never;
329
+ identity: undefined;
330
+ generated: undefined;
331
+ }, {}, {}>;
332
+ tags: drizzle_orm_pg_core.PgColumn<{
333
+ name: "tags";
334
+ tableName: "job_run";
335
+ dataType: "json";
336
+ columnType: "PgJsonb";
337
+ data: Record<string, string>;
338
+ driverParam: unknown;
339
+ notNull: true;
340
+ hasDefault: true;
341
+ isPrimaryKey: false;
342
+ isAutoincrement: false;
343
+ hasRuntimeDefault: false;
344
+ enumValues: undefined;
345
+ baseColumn: never;
346
+ identity: undefined;
347
+ generated: undefined;
348
+ }, {}, {
349
+ $type: Record<string, string>;
350
+ }>;
351
+ pool: drizzle_orm_pg_core.PgColumn<{
352
+ name: "pool";
353
+ tableName: "job_run";
354
+ dataType: "string";
355
+ columnType: "PgText";
356
+ data: string;
357
+ driverParam: string;
358
+ notNull: true;
359
+ hasDefault: false;
360
+ isPrimaryKey: false;
361
+ isAutoincrement: false;
362
+ hasRuntimeDefault: false;
363
+ enumValues: [string, ...string[]];
364
+ baseColumn: never;
365
+ identity: undefined;
366
+ generated: undefined;
367
+ }, {}, {}>;
368
+ priority: drizzle_orm_pg_core.PgColumn<{
369
+ name: "priority";
370
+ tableName: "job_run";
371
+ dataType: "number";
372
+ columnType: "PgInteger";
373
+ data: number;
374
+ driverParam: string | number;
375
+ notNull: true;
376
+ hasDefault: true;
377
+ isPrimaryKey: false;
378
+ isAutoincrement: false;
379
+ hasRuntimeDefault: false;
380
+ enumValues: undefined;
381
+ baseColumn: never;
382
+ identity: undefined;
383
+ generated: undefined;
384
+ }, {}, {}>;
385
+ concurrencyKey: drizzle_orm_pg_core.PgColumn<{
386
+ name: "concurrency_key";
387
+ tableName: "job_run";
388
+ dataType: "string";
389
+ columnType: "PgText";
390
+ data: string;
391
+ driverParam: string;
392
+ notNull: false;
393
+ hasDefault: false;
394
+ isPrimaryKey: false;
395
+ isAutoincrement: false;
396
+ hasRuntimeDefault: false;
397
+ enumValues: [string, ...string[]];
398
+ baseColumn: never;
399
+ identity: undefined;
400
+ generated: undefined;
401
+ }, {}, {}>;
402
+ dedupeKey: drizzle_orm_pg_core.PgColumn<{
403
+ name: "dedupe_key";
404
+ tableName: "job_run";
405
+ dataType: "string";
406
+ columnType: "PgText";
407
+ data: string;
408
+ driverParam: string;
409
+ notNull: false;
410
+ hasDefault: false;
411
+ isPrimaryKey: false;
412
+ isAutoincrement: false;
413
+ hasRuntimeDefault: false;
414
+ enumValues: [string, ...string[]];
415
+ baseColumn: never;
416
+ identity: undefined;
417
+ generated: undefined;
418
+ }, {}, {}>;
419
+ status: drizzle_orm_pg_core.PgColumn<{
420
+ name: "status";
421
+ tableName: "job_run";
422
+ dataType: "string";
423
+ columnType: "PgEnumColumn";
424
+ data: "pending" | "running" | "waiting" | "completed" | "failed" | "timed_out" | "canceled";
425
+ driverParam: string;
426
+ notNull: true;
427
+ hasDefault: true;
428
+ isPrimaryKey: false;
429
+ isAutoincrement: false;
430
+ hasRuntimeDefault: false;
431
+ enumValues: ["pending", "running", "waiting", "completed", "failed", "timed_out", "canceled"];
432
+ baseColumn: never;
433
+ identity: undefined;
434
+ generated: undefined;
435
+ }, {}, {}>;
436
+ input: drizzle_orm_pg_core.PgColumn<{
437
+ name: "input";
438
+ tableName: "job_run";
439
+ dataType: "json";
440
+ columnType: "PgJsonb";
441
+ data: Record<string, unknown>;
442
+ driverParam: unknown;
443
+ notNull: true;
444
+ hasDefault: false;
445
+ isPrimaryKey: false;
446
+ isAutoincrement: false;
447
+ hasRuntimeDefault: false;
448
+ enumValues: undefined;
449
+ baseColumn: never;
450
+ identity: undefined;
451
+ generated: undefined;
452
+ }, {}, {
453
+ $type: Record<string, unknown>;
454
+ }>;
455
+ output: drizzle_orm_pg_core.PgColumn<{
456
+ name: "output";
457
+ tableName: "job_run";
458
+ dataType: "json";
459
+ columnType: "PgJsonb";
460
+ data: Record<string, unknown>;
461
+ driverParam: unknown;
462
+ notNull: false;
463
+ hasDefault: false;
464
+ isPrimaryKey: false;
465
+ isAutoincrement: false;
466
+ hasRuntimeDefault: false;
467
+ enumValues: undefined;
468
+ baseColumn: never;
469
+ identity: undefined;
470
+ generated: undefined;
471
+ }, {}, {
472
+ $type: Record<string, unknown>;
473
+ }>;
474
+ error: drizzle_orm_pg_core.PgColumn<{
475
+ name: "error";
476
+ tableName: "job_run";
477
+ dataType: "json";
478
+ columnType: "PgJsonb";
479
+ data: {
480
+ message: string;
481
+ stack?: string;
482
+ retryable: boolean;
483
+ attempt: number;
484
+ };
485
+ driverParam: unknown;
486
+ notNull: false;
487
+ hasDefault: false;
488
+ isPrimaryKey: false;
489
+ isAutoincrement: false;
490
+ hasRuntimeDefault: false;
491
+ enumValues: undefined;
492
+ baseColumn: never;
493
+ identity: undefined;
494
+ generated: undefined;
495
+ }, {}, {
496
+ $type: {
497
+ message: string;
498
+ stack?: string;
499
+ retryable: boolean;
500
+ attempt: number;
501
+ };
502
+ }>;
503
+ triggerSource: drizzle_orm_pg_core.PgColumn<{
504
+ name: "trigger_source";
505
+ tableName: "job_run";
506
+ dataType: "string";
507
+ columnType: "PgEnumColumn";
508
+ data: "manual" | "schedule" | "event" | "parent";
509
+ driverParam: string;
510
+ notNull: true;
511
+ hasDefault: false;
512
+ isPrimaryKey: false;
513
+ isAutoincrement: false;
514
+ hasRuntimeDefault: false;
515
+ enumValues: ["manual", "schedule", "event", "parent"];
516
+ baseColumn: never;
517
+ identity: undefined;
518
+ generated: undefined;
519
+ }, {}, {}>;
520
+ triggerRef: drizzle_orm_pg_core.PgColumn<{
521
+ name: "trigger_ref";
522
+ tableName: "job_run";
523
+ dataType: "string";
524
+ columnType: "PgText";
525
+ data: string;
526
+ driverParam: string;
527
+ notNull: false;
528
+ hasDefault: false;
529
+ isPrimaryKey: false;
530
+ isAutoincrement: false;
531
+ hasRuntimeDefault: false;
532
+ enumValues: [string, ...string[]];
533
+ baseColumn: never;
534
+ identity: undefined;
535
+ generated: undefined;
536
+ }, {}, {}>;
537
+ runAt: drizzle_orm_pg_core.PgColumn<{
538
+ name: "run_at";
539
+ tableName: "job_run";
540
+ dataType: "date";
541
+ columnType: "PgTimestamp";
542
+ data: Date;
543
+ driverParam: string;
544
+ notNull: true;
545
+ hasDefault: true;
546
+ isPrimaryKey: false;
547
+ isAutoincrement: false;
548
+ hasRuntimeDefault: false;
549
+ enumValues: undefined;
550
+ baseColumn: never;
551
+ identity: undefined;
552
+ generated: undefined;
553
+ }, {}, {}>;
554
+ startedAt: drizzle_orm_pg_core.PgColumn<{
555
+ name: "started_at";
556
+ tableName: "job_run";
557
+ dataType: "date";
558
+ columnType: "PgTimestamp";
559
+ data: Date;
560
+ driverParam: string;
561
+ notNull: false;
562
+ hasDefault: false;
563
+ isPrimaryKey: false;
564
+ isAutoincrement: false;
565
+ hasRuntimeDefault: false;
566
+ enumValues: undefined;
567
+ baseColumn: never;
568
+ identity: undefined;
569
+ generated: undefined;
570
+ }, {}, {}>;
571
+ finishedAt: drizzle_orm_pg_core.PgColumn<{
572
+ name: "finished_at";
573
+ tableName: "job_run";
574
+ dataType: "date";
575
+ columnType: "PgTimestamp";
576
+ data: Date;
577
+ driverParam: string;
578
+ notNull: false;
579
+ hasDefault: false;
580
+ isPrimaryKey: false;
581
+ isAutoincrement: false;
582
+ hasRuntimeDefault: false;
583
+ enumValues: undefined;
584
+ baseColumn: never;
585
+ identity: undefined;
586
+ generated: undefined;
587
+ }, {}, {}>;
588
+ claimedAt: drizzle_orm_pg_core.PgColumn<{
589
+ name: "claimed_at";
590
+ tableName: "job_run";
591
+ dataType: "date";
592
+ columnType: "PgTimestamp";
593
+ data: Date;
594
+ driverParam: string;
595
+ notNull: false;
596
+ hasDefault: false;
597
+ isPrimaryKey: false;
598
+ isAutoincrement: false;
599
+ hasRuntimeDefault: false;
600
+ enumValues: undefined;
601
+ baseColumn: never;
602
+ identity: undefined;
603
+ generated: undefined;
604
+ }, {}, {}>;
605
+ attempts: drizzle_orm_pg_core.PgColumn<{
606
+ name: "attempts";
607
+ tableName: "job_run";
608
+ dataType: "number";
609
+ columnType: "PgInteger";
610
+ data: number;
611
+ driverParam: string | number;
612
+ notNull: true;
613
+ hasDefault: true;
614
+ isPrimaryKey: false;
615
+ isAutoincrement: false;
616
+ hasRuntimeDefault: false;
617
+ enumValues: undefined;
618
+ baseColumn: never;
619
+ identity: undefined;
620
+ generated: undefined;
621
+ }, {}, {}>;
622
+ waitKind: drizzle_orm_pg_core.PgColumn<{
623
+ name: "wait_kind";
624
+ tableName: "job_run";
625
+ dataType: "string";
626
+ columnType: "PgEnumColumn";
627
+ data: "signal";
628
+ driverParam: string;
629
+ notNull: false;
630
+ hasDefault: false;
631
+ isPrimaryKey: false;
632
+ isAutoincrement: false;
633
+ hasRuntimeDefault: false;
634
+ enumValues: ["signal"];
635
+ baseColumn: never;
636
+ identity: undefined;
637
+ generated: undefined;
638
+ }, {}, {}>;
639
+ resumeToken: drizzle_orm_pg_core.PgColumn<{
640
+ name: "resume_token";
641
+ tableName: "job_run";
642
+ dataType: "string";
643
+ columnType: "PgText";
644
+ data: string;
645
+ driverParam: string;
646
+ notNull: false;
647
+ hasDefault: false;
648
+ isPrimaryKey: false;
649
+ isAutoincrement: false;
650
+ hasRuntimeDefault: false;
651
+ enumValues: [string, ...string[]];
652
+ baseColumn: never;
653
+ identity: undefined;
654
+ generated: undefined;
655
+ }, {}, {}>;
656
+ waitDeadline: drizzle_orm_pg_core.PgColumn<{
657
+ name: "wait_deadline";
658
+ tableName: "job_run";
659
+ dataType: "date";
660
+ columnType: "PgTimestamp";
661
+ data: Date;
662
+ driverParam: string;
663
+ notNull: false;
664
+ hasDefault: false;
665
+ isPrimaryKey: false;
666
+ isAutoincrement: false;
667
+ hasRuntimeDefault: false;
668
+ enumValues: undefined;
669
+ baseColumn: never;
670
+ identity: undefined;
671
+ generated: undefined;
672
+ }, {}, {}>;
673
+ createdAt: drizzle_orm_pg_core.PgColumn<{
674
+ name: "created_at";
675
+ tableName: "job_run";
676
+ dataType: "date";
677
+ columnType: "PgTimestamp";
678
+ data: Date;
679
+ driverParam: string;
680
+ notNull: true;
681
+ hasDefault: true;
682
+ isPrimaryKey: false;
683
+ isAutoincrement: false;
684
+ hasRuntimeDefault: false;
685
+ enumValues: undefined;
686
+ baseColumn: never;
687
+ identity: undefined;
688
+ generated: undefined;
689
+ }, {}, {}>;
690
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
691
+ name: "updated_at";
692
+ tableName: "job_run";
693
+ dataType: "date";
694
+ columnType: "PgTimestamp";
695
+ data: Date;
696
+ driverParam: string;
697
+ notNull: true;
698
+ hasDefault: true;
699
+ isPrimaryKey: false;
700
+ isAutoincrement: false;
701
+ hasRuntimeDefault: false;
702
+ enumValues: undefined;
703
+ baseColumn: never;
704
+ identity: undefined;
705
+ generated: undefined;
706
+ }, {}, {}>;
707
+ };
708
+ dialect: "pg";
709
+ }>, drizzle_orm_node_postgres.NodePgQueryResultHKT, undefined, undefined, undefined, Record<"job_run", "not-null">, [], false, "where" | "leftJoin" | "rightJoin" | "innerJoin" | "fullJoin">, "where" | "leftJoin" | "rightJoin" | "innerJoin" | "fullJoin">;
147
710
  declare class JobWorker implements OnModuleInit, OnModuleDestroy {
148
711
  private readonly db;
149
712
  private readonly orchestrator;
@@ -154,13 +717,24 @@ declare class JobWorker implements OnModuleInit, OnModuleDestroy {
154
717
  private readonly logger;
155
718
  private shuttingDown;
156
719
  private readonly inFlight;
720
+ /**
721
+ * CLAIM-HB-1 — the set of run IDs this worker currently has executing. The
722
+ * heartbeat renews `claimed_at` for exactly these; a run is added when its
723
+ * `processRun` is dispatched and removed when its execution settles (success,
724
+ * failure, retry-release, or concurrency-defer). Kept separate from
725
+ * `inFlight` (which tracks the wrapper Promises for drain) because the
726
+ * heartbeat needs the IDs, not the promises.
727
+ */
728
+ private readonly inFlightRunIds;
157
729
  private pollTimer;
158
730
  private sweeperTimer;
731
+ private heartbeatTimer;
159
732
  private sigtermHandled;
160
733
  private readonly sigtermHandler;
161
734
  private readonly pollIntervalMs;
162
735
  private readonly staleSweeperIntervalMs;
163
736
  private readonly staleThresholdMs;
737
+ private readonly claimHeartbeatIntervalMs;
164
738
  private readonly shutdownTimeoutMs;
165
739
  private readonly listenNotifyEnabled;
166
740
  private notifyListener;
@@ -207,6 +781,20 @@ declare class JobWorker implements OnModuleInit, OnModuleDestroy {
207
781
  * then update) guarantees each stranded row is only reset once.
208
782
  */
209
783
  sweepStaleClaims(): Promise<void>;
784
+ /**
785
+ * Renew the claim lease on every run this worker currently has in flight by
786
+ * bumping `claimed_at = now()` in a single UPDATE. This is what keeps
787
+ * `sweepStaleClaims` from re-queueing a legitimately long-running handler:
788
+ * the sweeper only resets rows whose `claimed_at` has aged past the threshold,
789
+ * and a live worker keeps renewing. When the worker process dies, renewal
790
+ * stops, the row ages out, and the sweeper correctly recovers it — its
791
+ * documented "stranded by a crashed worker" intent.
792
+ *
793
+ * No-ops (no query) when nothing is in flight. The `status = 'running'` guard
794
+ * inside the UPDATE means a run that was swept-and-reclaimed elsewhere (or has
795
+ * already settled) is not touched.
796
+ */
797
+ renewClaims(): Promise<void>;
210
798
  private processRun;
211
799
  private markFailed;
212
800
  private makeStepFn;
@@ -221,4 +809,4 @@ declare class JobWorker implements OnModuleInit, OnModuleDestroy {
221
809
  private nextStepSeq;
222
810
  }
223
811
 
224
- export { JOB_WORKER_OPTIONS, JobWorker, type JobWorkerOptions, TERMINAL_STATUSES, buildClaimQuery, buildStaleSweepQuery, classifyError, computeBackoff };
812
+ export { JOB_WORKER_OPTIONS, JobWorker, type JobWorkerOptions, TERMINAL_STATUSES, buildClaimQuery, buildClaimRenewQuery, buildStaleSweepQuery, classifyError, computeBackoff };
@@ -3,10 +3,11 @@ import {
3
3
  JobWorker,
4
4
  TERMINAL_STATUSES,
5
5
  buildClaimQuery,
6
+ buildClaimRenewQuery,
6
7
  buildStaleSweepQuery,
7
8
  classifyError,
8
9
  computeBackoff
9
- } from "../../../chunk-VDL5CJ5C.js";
10
+ } from "../../../chunk-7B7MMDOJ.js";
10
11
  import "../../../chunk-Q6LRJ4VI.js";
11
12
  import "../../../chunk-7P5ODGLA.js";
12
13
  import "../../../chunk-ZPL74UQN.js";
@@ -19,6 +20,7 @@ export {
19
20
  JobWorker,
20
21
  TERMINAL_STATUSES,
21
22
  buildClaimQuery,
23
+ buildClaimRenewQuery,
22
24
  buildStaleSweepQuery,
23
25
  classifyError,
24
26
  computeBackoff
@@ -2,9 +2,9 @@ import {
2
2
  JOB_WORKER_MODULE_OPTIONS,
3
3
  JobWorkerModule,
4
4
  JobWorkerOrchestrator
5
- } from "../../../chunk-QXVCRA23.js";
6
- import "../../../chunk-VDL5CJ5C.js";
7
- import "../../../chunk-6DQEIXYU.js";
5
+ } from "../../../chunk-SH76CFAY.js";
6
+ import "../../../chunk-7B7MMDOJ.js";
7
+ import "../../../chunk-FIUC6QB5.js";
8
8
  import "../../../chunk-VQOAATIG.js";
9
9
  import "../../../chunk-3VEVGL74.js";
10
10
  import "../../../chunk-CDLWYZVQ.js";