@gobing-ai/ts-infra 0.5.25 → 0.5.27

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.
@@ -1 +1 @@
1
- {"version":3,"file":"db-job-queue.d.ts","sourceRoot":"","sources":["../../src/job-queue/db-job-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAkB,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EACR,WAAW,EAKd,MAAM,WAAW,CAAC;AAWnB,OAAO,KAAK,EAAE,cAAc,EAAO,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAQ7G,kFAAkF;AAClF,qBAAa,UAAU,CAAC,CAAC,GAAG,OAAO,CAAE,YAAW,QAAQ,CAAC,CAAC,CAAC;IAEnD,QAAQ,CAAC,GAAG,EAAE,WAAW;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBADf,GAAG,EAAE,WAAW,EACR,MAAM,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,YAAA;IAG7C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAO5E,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC,CAAA;KAAE,GAAG,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAY3F,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;CAGrC;AAcD,sGAAsG;AACtG,qBAAa,eAAe,CAAC,CAAC,GAAG,OAAO,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IA2B7D,OAAO,CAAC,QAAQ,CAAC,GAAG;IA1BxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoC;IAC7D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoC;IAChE,kGAAkG;IAClG,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAgB;IACjD,wFAAwF;IACxF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2E;IAC1G;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgE;IAC1F,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,WAAW,CAA8B;IACjD,yFAAyF;IACzF,OAAO,CAAC,aAAa,CAAS;gBAGT,GAAG,EAAE,WAAW,EACjC,MAAM,GAAE,mBAAwB;IAyBpC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI;IAI9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuDrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQvC,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;IAIlC,sFAAsF;IAChF,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IA8BpC,yEAAyE;YAC3D,UAAU;IAcxB,OAAO,CAAC,QAAQ;YAWF,IAAI;YAgBJ,UAAU;IAsHxB;;;;;OAKG;YACW,iBAAiB;YA2BjB,WAAW;CAyC5B"}
1
+ {"version":3,"file":"db-job-queue.d.ts","sourceRoot":"","sources":["../../src/job-queue/db-job-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAkB,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EACR,WAAW,EAKd,MAAM,WAAW,CAAC;AAWnB,OAAO,KAAK,EAAE,cAAc,EAAO,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAQ7G,kFAAkF;AAClF,qBAAa,UAAU,CAAC,CAAC,GAAG,OAAO,CAAE,YAAW,QAAQ,CAAC,CAAC,CAAC;IAEnD,QAAQ,CAAC,GAAG,EAAE,WAAW;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBADf,GAAG,EAAE,WAAW,EACR,MAAM,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,YAAA;IAG7C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAO5E,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC,CAAA;KAAE,GAAG,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAY3F,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;CAGrC;AAcD,sGAAsG;AACtG,qBAAa,eAAe,CAAC,CAAC,GAAG,OAAO,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IA2B7D,OAAO,CAAC,QAAQ,CAAC,GAAG;IA1BxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoC;IAC7D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoC;IAChE,kGAAkG;IAClG,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAgB;IACjD,wFAAwF;IACxF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2E;IAC1G;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgE;IAC1F,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,WAAW,CAA8B;IACjD,yFAAyF;IACzF,OAAO,CAAC,aAAa,CAAS;gBAGT,GAAG,EAAE,WAAW,EACjC,MAAM,GAAE,mBAAwB;IAyBpC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI;IAI9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuDrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWvC,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;IAIlC,sFAAsF;IAChF,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IA8BpC,yEAAyE;YAC3D,UAAU;IAcxB,OAAO,CAAC,QAAQ;YAWF,IAAI;YAgBJ,UAAU;IA0HxB;;;;;OAKG;YACW,iBAAiB;YA2BjB,WAAW;CAyC5B"}
@@ -176,7 +176,10 @@ export class DBQueueConsumer {
176
176
  }
177
177
  async cancel(jobId) {
178
178
  const attempt = this.activeAttempts.get(jobId);
179
- if (attempt === undefined)
179
+ // Admission ends at handler settlement (task 0112): a settled attempt is
180
+ // already inside its acknowledgement window and the outcome dispatch can
181
+ // no longer act on a cancellation — refuse instead of accepting it.
182
+ if (attempt === undefined || attempt.state.settled)
180
183
  return false;
181
184
  attempt.state.cancelled = true;
182
185
  attempt.controller.abort();
@@ -320,16 +323,12 @@ export class DBQueueConsumer {
320
323
  });
321
324
  return;
322
325
  }
323
- if (outcome.outcome === 'error') {
324
- await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
325
- }
326
- else if (outcome.timedOut) {
327
- // Deadline expiry is a failure like any other, reported only after
328
- // the handler has settled — even if it ignored the abort.
329
- await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
330
- }
331
- else if (attempt.cancelled) {
332
- // Manual cancellation is terminal: settle, then fail without retry.
326
+ if (attempt.cancelled) {
327
+ // Manual cancellation is terminal and wins over handler errors
328
+ // and deadline expiry: an accepted cancel() before settlement
329
+ // fails the job without retry, whatever the outcome was (0112).
330
+ // Lease-loss fencing above stays first — a stale attempt mutates
331
+ // nothing; the fenced write below still refuses a stolen token.
333
332
  const message = 'job cancelled';
334
333
  const applied = await this.dao.markFailed(record.id, job.attempts + 1, message, token);
335
334
  if (applied) {
@@ -345,6 +344,14 @@ export class DBQueueConsumer {
345
344
  });
346
345
  }
347
346
  }
347
+ else if (outcome.outcome === 'error') {
348
+ await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
349
+ }
350
+ else if (outcome.timedOut) {
351
+ // Deadline expiry is a failure like any other, reported only after
352
+ // the handler has settled — even if it ignored the abort.
353
+ await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
354
+ }
348
355
  else {
349
356
  // Task 0086 R10: gate metric + event on the fenced write — a
350
357
  // lost lease means another consumer owns the job now.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/ts-infra",
3
- "version": "0.5.25",
3
+ "version": "0.5.27",
4
4
  "description": "@gobing-ai/ts-infra — Infrastructure backbone: event bus, job queue, scheduler, telemetry, API client, and logging.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -78,12 +78,12 @@
78
78
  "release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-infra-v<version> && git push --tags' && exit 1"
79
79
  },
80
80
  "dependencies": {
81
- "@gobing-ai/ts-utils": "^0.5.25",
81
+ "@gobing-ai/ts-utils": "^0.5.27",
82
82
  "@logtape/logtape": "^2.0.0"
83
83
  },
84
84
  "peerDependencies": {
85
- "@gobing-ai/ts-db": "^0.5.25",
86
- "@gobing-ai/ts-runtime": "^0.5.25",
85
+ "@gobing-ai/ts-db": "^0.5.27",
86
+ "@gobing-ai/ts-runtime": "^0.5.27",
87
87
  "@opentelemetry/api": "^1.9.0",
88
88
  "@opentelemetry/sdk-trace-node": "^2.0.0",
89
89
  "@opentelemetry/sdk-metrics": "^2.0.0",
@@ -116,8 +116,8 @@
116
116
  }
117
117
  },
118
118
  "devDependencies": {
119
- "@gobing-ai/ts-db": "^0.5.25",
120
- "@gobing-ai/ts-runtime": "^0.5.25",
119
+ "@gobing-ai/ts-db": "^0.5.27",
120
+ "@gobing-ai/ts-runtime": "^0.5.27",
121
121
  "@types/bun": "1.4.3",
122
122
  "@opentelemetry/api": "^1.9.0",
123
123
  "@opentelemetry/sdk-trace-node": "^2.0.0",
@@ -202,7 +202,10 @@ export class DBQueueConsumer<T = unknown> implements QueueConsumer<T> {
202
202
 
203
203
  async cancel(jobId: string): Promise<boolean> {
204
204
  const attempt = this.activeAttempts.get(jobId);
205
- if (attempt === undefined) return false;
205
+ // Admission ends at handler settlement (task 0112): a settled attempt is
206
+ // already inside its acknowledgement window and the outcome dispatch can
207
+ // no longer act on a cancellation — refuse instead of accepting it.
208
+ if (attempt === undefined || attempt.state.settled) return false;
206
209
  attempt.state.cancelled = true;
207
210
  attempt.controller.abort();
208
211
  return true;
@@ -357,14 +360,12 @@ export class DBQueueConsumer<T = unknown> implements QueueConsumer<T> {
357
360
  return;
358
361
  }
359
362
 
360
- if (outcome.outcome === 'error') {
361
- await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
362
- } else if (outcome.timedOut) {
363
- // Deadline expiry is a failure like any other, reported only after
364
- // the handler has settled — even if it ignored the abort.
365
- await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
366
- } else if (attempt.cancelled) {
367
- // Manual cancellation is terminal: settle, then fail without retry.
363
+ if (attempt.cancelled) {
364
+ // Manual cancellation is terminal and wins over handler errors
365
+ // and deadline expiry: an accepted cancel() before settlement
366
+ // fails the job without retry, whatever the outcome was (0112).
367
+ // Lease-loss fencing above stays first — a stale attempt mutates
368
+ // nothing; the fenced write below still refuses a stolen token.
368
369
  const message = 'job cancelled';
369
370
  const applied = await this.dao.markFailed(record.id, job.attempts + 1, message, token);
370
371
  if (applied) {
@@ -379,6 +380,12 @@ export class DBQueueConsumer<T = unknown> implements QueueConsumer<T> {
379
380
  severity: 'warning',
380
381
  });
381
382
  }
383
+ } else if (outcome.outcome === 'error') {
384
+ await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
385
+ } else if (outcome.timedOut) {
386
+ // Deadline expiry is a failure like any other, reported only after
387
+ // the handler has settled — even if it ignored the abort.
388
+ await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
382
389
  } else {
383
390
  // Task 0086 R10: gate metric + event on the fenced write — a
384
391
  // lost lease means another consumer owns the job now.