@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.
- package/CHANGELOG.md +33 -0
- package/dist/{chunk-NR7QQ6ZI.js → chunk-42763UEE.js} +2 -2
- package/dist/{chunk-6ECCJVYW.js → chunk-4M66MQYA.js} +44 -2
- package/dist/chunk-4M66MQYA.js.map +1 -0
- package/dist/{chunk-FNHNSFIJ.js → chunk-6XP2Q5SS.js} +2 -2
- package/dist/{chunk-VDL5CJ5C.js → chunk-7B7MMDOJ.js} +54 -1
- package/dist/chunk-7B7MMDOJ.js.map +1 -0
- package/dist/{chunk-NXHL5YII.js → chunk-7LKAMLV4.js} +4 -4
- package/dist/{chunk-6DQEIXYU.js → chunk-FIUC6QB5.js} +1 -1
- package/dist/chunk-FIUC6QB5.js.map +1 -0
- package/dist/{chunk-DB5UXJC3.js → chunk-PNCOUFFI.js} +4 -2
- package/dist/chunk-PNCOUFFI.js.map +1 -0
- package/dist/{chunk-QXVCRA23.js → chunk-SH76CFAY.js} +9 -4
- package/dist/chunk-SH76CFAY.js.map +1 -0
- package/dist/runtime/base-classes/index.js +17 -17
- package/dist/runtime/subsystems/auth/auth.module.js +3 -3
- package/dist/runtime/subsystems/auth/index.js +7 -7
- package/dist/runtime/subsystems/bridge/bridge.module.js +4 -4
- package/dist/runtime/subsystems/bridge/index.js +4 -4
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +1 -1
- package/dist/runtime/subsystems/events/events.module.js +2 -2
- package/dist/runtime/subsystems/events/index.js +2 -2
- package/dist/runtime/subsystems/index.js +12 -12
- package/dist/runtime/subsystems/jobs/index.js +3 -3
- package/dist/runtime/subsystems/jobs/job-worker.d.ts +592 -4
- package/dist/runtime/subsystems/jobs/job-worker.js +3 -1
- package/dist/runtime/subsystems/jobs/job-worker.module.js +3 -3
- package/dist/runtime/subsystems/jobs/jobs-domain.module.d.ts +19 -0
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +1 -1
- package/dist/src/cli/index.js +211 -60
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +477 -1
- package/dist/src/index.js +1 -1
- package/package.json +1 -1
- package/runtime/subsystems/events/event-bus.drizzle-backend.ts +23 -7
- package/runtime/subsystems/jobs/job-worker.module.ts +5 -0
- package/runtime/subsystems/jobs/job-worker.ts +126 -12
- package/runtime/subsystems/jobs/jobs-domain.module.ts +19 -0
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +59 -10
- package/templates/subsystem/jobs-config/codegen-config-jobs-block.ejs.t +11 -0
- package/dist/chunk-6DQEIXYU.js.map +0 -1
- package/dist/chunk-6ECCJVYW.js.map +0 -1
- package/dist/chunk-DB5UXJC3.js.map +0 -1
- package/dist/chunk-QXVCRA23.js.map +0 -1
- package/dist/chunk-VDL5CJ5C.js.map +0 -1
- /package/dist/{chunk-NR7QQ6ZI.js.map → chunk-42763UEE.js.map} +0 -0
- /package/dist/{chunk-FNHNSFIJ.js.map → chunk-6XP2Q5SS.js.map} +0 -0
- /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
|
|
30
|
-
*
|
|
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-
|
|
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-
|
|
6
|
-
import "../../../chunk-
|
|
7
|
-
import "../../../chunk-
|
|
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";
|