@ultimat3/jobs 26.1.1 → 27.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 (2) hide show
  1. package/package.json +6 -6
  2. package/src/execute.ts +11 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/jobs",
3
- "version": "26.1.1",
3
+ "version": "27.1.0",
4
4
  "description": "Durable background work: steps, transactional outbox, cron tasks, one driver interface",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,10 +32,10 @@
32
32
  "test": "bun test"
33
33
  },
34
34
  "dependencies": {
35
- "@ultimat3/core": "26.1.1",
36
- "@ultimat3/db": "26.1.1",
37
- "@ultimat3/entity": "26.1.1",
38
- "@ultimat3/schema": "26.1.1",
39
- "@ultimat3/time": "26.1.1"
35
+ "@ultimat3/core": "27.1.0",
36
+ "@ultimat3/db": "27.1.0",
37
+ "@ultimat3/entity": "27.1.0",
38
+ "@ultimat3/schema": "27.1.0",
39
+ "@ultimat3/time": "27.1.0"
40
40
  }
41
41
  }
package/src/execute.ts CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  useContext,
18
18
  withChildContext,
19
19
  } from '@ultimat3/core';
20
+ import { outsideTransaction } from '@ultimat3/db';
20
21
  import { nowMs } from './clock';
21
22
  import type { ClaimedJob, JobDriver, SettleBy } from './driver';
22
23
  import { claimOf } from './driver';
@@ -210,7 +211,12 @@ export async function executeJob(options: ExecuteJobOptions): Promise<JobExecuti
210
211
  * payload has parsed there is no tenant to derive, so the worker's own context stands in — and
211
212
  * a tenant-scoped read under it fails closed, which is right for a payload nobody could read.
212
213
  */
213
- let inRunScope = <T>(fn: () => T): T => runWithContext(ctx, fn);
214
+ //
215
+ // Outside any transaction, always: a worker started inside a transaction scope (a test, a boot
216
+ // that ran inside one) carried it into every timer of its loop, so each body saw that
217
+ // transaction — committed long before — as ambient, `db()` answered with it, and an enqueue from
218
+ // the body staged into its dead outbox. A job opens its own `withTransaction` when it wants one.
219
+ let inRunScope = <T>(fn: () => T): T => outsideTransaction(() => runWithContext(ctx, fn));
214
220
 
215
221
  const settle = async (outcome: JobExecution): Promise<JobExecution> => {
216
222
  const steps = await driver.steps.list(claimed.runId);
@@ -237,7 +243,10 @@ export async function executeJob(options: ExecuteJobOptions): Promise<JobExecuti
237
243
  // still answer the worker's org while every ambient repository call answered the job's — one
238
244
  // run acting as two tenants, which is the same hole one layer up. It rebuilds every managed
239
245
  // factory against `runActor` and carries only the services no factory owns.
240
- inRunScope = (fn) => runWithContext(ctx, () => withChildContext({ actor: runActor }, fn));
246
+ inRunScope = (fn) =>
247
+ outsideTransaction(() =>
248
+ runWithContext(ctx, () => withChildContext({ actor: runActor }, fn)),
249
+ );
241
250
  const work = inRunScope(() =>
242
251
  handle.run({
243
252
  input,