@btravstack/temporal-worker 0.14.0 → 0.15.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/dist/index.cjs CHANGED
@@ -165,9 +165,9 @@ const metaFor = () => {
165
165
  //#region src/temporal-runtime.ts
166
166
  /**
167
167
  * Where the Temporal service is, as a service: `temporal()` binds it from the
168
- * environment — `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`) and
169
- * `TEMPORAL_NAMESPACE` (default `default`) — unless pinned, and anything else
170
- * in the graph may read it.
168
+ * environment — `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`),
169
+ * `TEMPORAL_NAMESPACE` (default `default`) and the shutdown budgets below —
170
+ * unless pinned, and anything else in the graph may read it.
171
171
  */
172
172
  var TemporalConfig = class extends (0, _btravstack_di.Port)("TemporalConfig") {};
173
173
  /**
@@ -206,14 +206,14 @@ const DEFAULT_FORCE_MS = 15e3;
206
206
  const durationMs = (duration) => duration === void 0 ? void 0 : (0, _temporalio_common.msToNumber)(duration);
207
207
  /**
208
208
  * The Temporal starter: a module providing the runtime, its configuration
209
- * (bound from `TEMPORAL_ADDRESS` / `TEMPORAL_NAMESPACE` unless pinned) and the
210
- * connection (a resource opened with the scope and closed with it; a service
211
- * that will not answer is a modeled `TemporalUnreachable`). Import it next to
212
- * the application, export `TemporalRuntime`, provide the activities — the
209
+ * (bound from the `TEMPORAL_*` variables unless pinned) and the connection (a
210
+ * resource opened with the scope and closed with it; a service that will not
211
+ * answer is a modeled `TemporalUnreachable`). Import it next to the
212
+ * application, export `TemporalRuntime`, provide the activities — the
213
213
  * activities port is a need of this module.
214
214
  *
215
- * With both configuration fields pinned the module reads nothing from the
216
- * environment; pin only one and the other still comes from it.
215
+ * Each configuration field is pinned on its own: a pinned field reads nothing
216
+ * from the environment, and a field left unpinned still does.
217
217
  */
218
218
  const temporal = (options) => {
219
219
  const { address, namespace } = options;
@@ -289,26 +289,39 @@ const createWorker = (host, connection, config, activities, options, observers)
289
289
  shutdownForceTime: config.forceAfterMs
290
290
  }), startFailed)).map((worker) => poll(worker, taskQueue, namespace));
291
291
  };
292
+ /**
293
+ * The `Serving` over a started worker.
294
+ *
295
+ * @internal Exported for `temporal-runtime.spec.ts` alone: the `stopped`
296
+ * channel is about a worker's `run()` REJECTING mid-flight, and there is no way
297
+ * to make a real one do that without taking the shared Temporal server down for
298
+ * every other spec. A stub worker is what reaches that arm.
299
+ */
292
300
  const poll = (worker, taskQueue, namespace) => {
293
301
  const running = (0, unthrown.fromSafePromise)(worker.run());
294
302
  const stopPolling = () => {
295
303
  if (worker.getState() === "RUNNING") worker.shutdown();
296
304
  };
297
305
  let deadline;
298
- const stopped = () => deadline === void 0 ? running : (0, _btravstack_core.releasedBy)(deadline, running);
306
+ const awaitRun = () => deadline === void 0 ? running : (0, _btravstack_core.releasedBy)(deadline, running);
307
+ let asked = false;
308
+ const withdrawn = () => (0, unthrown.fromSafePromise)(new Promise(() => {}));
299
309
  return {
300
310
  info: {
301
311
  taskQueue,
302
312
  namespace
303
313
  },
314
+ stopped: () => running.recoverDefect(() => (0, unthrown.Ok)(void 0)).flatMap(() => asked ? withdrawn() : (0, unthrown.OkAsync)()),
304
315
  drain: (signal) => {
316
+ asked = true;
305
317
  deadline = signal;
306
318
  stopPolling();
307
- return stopped();
319
+ return awaitRun();
308
320
  },
309
321
  stop: () => {
322
+ asked = true;
310
323
  stopPolling();
311
- return stopped();
324
+ return awaitRun();
312
325
  }
313
326
  };
314
327
  };
package/dist/index.d.cts CHANGED
@@ -134,9 +134,9 @@ type WorkflowSource = {
134
134
  declare const TemporalConfig_base: import("@btravstack/di").PortClass<"TemporalConfig">;
135
135
  /**
136
136
  * Where the Temporal service is, as a service: `temporal()` binds it from the
137
- * environment — `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`) and
138
- * `TEMPORAL_NAMESPACE` (default `default`) — unless pinned, and anything else
139
- * in the graph may read it.
137
+ * environment — `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`),
138
+ * `TEMPORAL_NAMESPACE` (default `default`) and the shutdown budgets below —
139
+ * unless pinned, and anything else in the graph may read it.
140
140
  */
141
141
  export declare class TemporalConfig extends TemporalConfig_base<{
142
142
  readonly address: string;
@@ -220,9 +220,10 @@ type TemporalTuning<Unit extends AnyUnitModule | undefined = undefined> = {
220
220
  readonly gracePeriod?: Duration;
221
221
  /**
222
222
  * The unit module the worker forks around every activity attempt it
223
- * dispatches, with no seed. Built after the activity is invoked, torn down
224
- * when the unit closes — the point where a later phase seeds it with the
225
- * workflow's tenant.
223
+ * dispatches, seeded with the validated input on `ActivityInput(contract)`.
224
+ * Built after the activity is invoked, before it runs; torn down when the
225
+ * unit closes. What it exports is what a piece may declare on its own
226
+ * `unit:` record.
226
227
  */
227
228
  readonly unit?: {
228
229
  readonly activity?: Unit;
@@ -240,14 +241,14 @@ type TemporalOptions<C extends ContractDefinition, Unit extends AnyUnitModule |
240
241
  type Provided = TemporalRuntime | TemporalConfig | TemporalConnection;
241
242
  /**
242
243
  * The Temporal starter: a module providing the runtime, its configuration
243
- * (bound from `TEMPORAL_ADDRESS` / `TEMPORAL_NAMESPACE` unless pinned) and the
244
- * connection (a resource opened with the scope and closed with it; a service
245
- * that will not answer is a modeled `TemporalUnreachable`). Import it next to
246
- * the application, export `TemporalRuntime`, provide the activities — the
244
+ * (bound from the `TEMPORAL_*` variables unless pinned) and the connection (a
245
+ * resource opened with the scope and closed with it; a service that will not
246
+ * answer is a modeled `TemporalUnreachable`). Import it next to the
247
+ * application, export `TemporalRuntime`, provide the activities — the
247
248
  * activities port is a need of this module.
248
249
  *
249
- * With both configuration fields pinned the module reads nothing from the
250
- * environment; pin only one and the other still comes from it.
250
+ * Each configuration field is pinned on its own: a pinned field reads nothing
251
+ * from the environment, and a field left unpinned still does.
251
252
  */
252
253
  export declare const temporal: <C extends ContractDefinition, Unit extends AnyUnitModule | undefined = undefined>(options: TemporalOptions<C, Unit>) => Module<Provided, ConfigInvalid | TemporalUnreachable, Env | Scope | ActivitiesInstanceOf<C> | UnitNeedsOf<Unit>>;
253
254
  //#endregion
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ import { ConfigInvalid, Env } from "@btravstack/config";
3
3
  import { Runtime, RuntimePort } from "@btravstack/core";
4
4
  import { DeclareActivitiesHandlerOptions, EmptyContext } from "@temporal-contract/worker/activity";
5
5
  import { Duration } from "@temporalio/common";
6
- import { NativeConnection, WorkflowBundleWithSourceMap } from "@temporalio/worker";
6
+ import { NativeConnection, Worker, WorkflowBundleWithSourceMap } from "@temporalio/worker";
7
7
  import { ContractDefinition } from "@temporal-contract/contract";
8
8
  //#region src/unit.d.ts
9
9
  /** What a bound unit module exports — the port instances an activity of that kind may read. */
@@ -134,9 +134,9 @@ type WorkflowSource = {
134
134
  declare const TemporalConfig_base: import("@btravstack/di").PortClass<"TemporalConfig">;
135
135
  /**
136
136
  * Where the Temporal service is, as a service: `temporal()` binds it from the
137
- * environment — `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`) and
138
- * `TEMPORAL_NAMESPACE` (default `default`) — unless pinned, and anything else
139
- * in the graph may read it.
137
+ * environment — `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`),
138
+ * `TEMPORAL_NAMESPACE` (default `default`) and the shutdown budgets below —
139
+ * unless pinned, and anything else in the graph may read it.
140
140
  */
141
141
  export declare class TemporalConfig extends TemporalConfig_base<{
142
142
  readonly address: string;
@@ -220,9 +220,10 @@ type TemporalTuning<Unit extends AnyUnitModule | undefined = undefined> = {
220
220
  readonly gracePeriod?: Duration;
221
221
  /**
222
222
  * The unit module the worker forks around every activity attempt it
223
- * dispatches, with no seed. Built after the activity is invoked, torn down
224
- * when the unit closes — the point where a later phase seeds it with the
225
- * workflow's tenant.
223
+ * dispatches, seeded with the validated input on `ActivityInput(contract)`.
224
+ * Built after the activity is invoked, before it runs; torn down when the
225
+ * unit closes. What it exports is what a piece may declare on its own
226
+ * `unit:` record.
226
227
  */
227
228
  readonly unit?: {
228
229
  readonly activity?: Unit;
@@ -240,14 +241,14 @@ type TemporalOptions<C extends ContractDefinition, Unit extends AnyUnitModule |
240
241
  type Provided = TemporalRuntime | TemporalConfig | TemporalConnection;
241
242
  /**
242
243
  * The Temporal starter: a module providing the runtime, its configuration
243
- * (bound from `TEMPORAL_ADDRESS` / `TEMPORAL_NAMESPACE` unless pinned) and the
244
- * connection (a resource opened with the scope and closed with it; a service
245
- * that will not answer is a modeled `TemporalUnreachable`). Import it next to
246
- * the application, export `TemporalRuntime`, provide the activities — the
244
+ * (bound from the `TEMPORAL_*` variables unless pinned) and the connection (a
245
+ * resource opened with the scope and closed with it; a service that will not
246
+ * answer is a modeled `TemporalUnreachable`). Import it next to the
247
+ * application, export `TemporalRuntime`, provide the activities — the
247
248
  * activities port is a need of this module.
248
249
  *
249
- * With both configuration fields pinned the module reads nothing from the
250
- * environment; pin only one and the other still comes from it.
250
+ * Each configuration field is pinned on its own: a pinned field reads nothing
251
+ * from the environment, and a field left unpinned still does.
251
252
  */
252
253
  export declare const temporal: <C extends ContractDefinition, Unit extends AnyUnitModule | undefined = undefined>(options: TemporalOptions<C, Unit>) => Module<Provided, ConfigInvalid | TemporalUnreachable, Env | Scope | ActivitiesInstanceOf<C> | UnitNeedsOf<Unit>>;
253
254
  //#endregion
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { Observers, RuntimePort, RuntimeStartFailed, noObserver, observe, releas
4
4
  import { declareActivitiesHandler } from "@temporal-contract/worker/activity";
5
5
  import { msToNumber } from "@temporalio/common";
6
6
  import { NativeConnection, Worker } from "@temporalio/worker";
7
- import { TaggedError, fromPromise, fromSafePromise, fromThrowable } from "unthrown";
7
+ import { Ok, OkAsync, TaggedError, fromPromise, fromSafePromise, fromThrowable } from "unthrown";
8
8
  import { activityInfo } from "@temporalio/activity";
9
9
  //#region src/unit.ts
10
10
  /**
@@ -164,9 +164,9 @@ const metaFor = () => {
164
164
  //#region src/temporal-runtime.ts
165
165
  /**
166
166
  * Where the Temporal service is, as a service: `temporal()` binds it from the
167
- * environment — `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`) and
168
- * `TEMPORAL_NAMESPACE` (default `default`) — unless pinned, and anything else
169
- * in the graph may read it.
167
+ * environment — `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`),
168
+ * `TEMPORAL_NAMESPACE` (default `default`) and the shutdown budgets below —
169
+ * unless pinned, and anything else in the graph may read it.
170
170
  */
171
171
  var TemporalConfig = class extends Port("TemporalConfig") {};
172
172
  /**
@@ -205,14 +205,14 @@ const DEFAULT_FORCE_MS = 15e3;
205
205
  const durationMs = (duration) => duration === void 0 ? void 0 : msToNumber(duration);
206
206
  /**
207
207
  * The Temporal starter: a module providing the runtime, its configuration
208
- * (bound from `TEMPORAL_ADDRESS` / `TEMPORAL_NAMESPACE` unless pinned) and the
209
- * connection (a resource opened with the scope and closed with it; a service
210
- * that will not answer is a modeled `TemporalUnreachable`). Import it next to
211
- * the application, export `TemporalRuntime`, provide the activities — the
208
+ * (bound from the `TEMPORAL_*` variables unless pinned) and the connection (a
209
+ * resource opened with the scope and closed with it; a service that will not
210
+ * answer is a modeled `TemporalUnreachable`). Import it next to the
211
+ * application, export `TemporalRuntime`, provide the activities — the
212
212
  * activities port is a need of this module.
213
213
  *
214
- * With both configuration fields pinned the module reads nothing from the
215
- * environment; pin only one and the other still comes from it.
214
+ * Each configuration field is pinned on its own: a pinned field reads nothing
215
+ * from the environment, and a field left unpinned still does.
216
216
  */
217
217
  const temporal = (options) => {
218
218
  const { address, namespace } = options;
@@ -288,26 +288,39 @@ const createWorker = (host, connection, config, activities, options, observers)
288
288
  shutdownForceTime: config.forceAfterMs
289
289
  }), startFailed)).map((worker) => poll(worker, taskQueue, namespace));
290
290
  };
291
+ /**
292
+ * The `Serving` over a started worker.
293
+ *
294
+ * @internal Exported for `temporal-runtime.spec.ts` alone: the `stopped`
295
+ * channel is about a worker's `run()` REJECTING mid-flight, and there is no way
296
+ * to make a real one do that without taking the shared Temporal server down for
297
+ * every other spec. A stub worker is what reaches that arm.
298
+ */
291
299
  const poll = (worker, taskQueue, namespace) => {
292
300
  const running = fromSafePromise(worker.run());
293
301
  const stopPolling = () => {
294
302
  if (worker.getState() === "RUNNING") worker.shutdown();
295
303
  };
296
304
  let deadline;
297
- const stopped = () => deadline === void 0 ? running : releasedBy(deadline, running);
305
+ const awaitRun = () => deadline === void 0 ? running : releasedBy(deadline, running);
306
+ let asked = false;
307
+ const withdrawn = () => fromSafePromise(new Promise(() => {}));
298
308
  return {
299
309
  info: {
300
310
  taskQueue,
301
311
  namespace
302
312
  },
313
+ stopped: () => running.recoverDefect(() => Ok(void 0)).flatMap(() => asked ? withdrawn() : OkAsync()),
303
314
  drain: (signal) => {
315
+ asked = true;
304
316
  deadline = signal;
305
317
  stopPolling();
306
- return stopped();
318
+ return awaitRun();
307
319
  },
308
320
  stop: () => {
321
+ asked = true;
309
322
  stopPolling();
310
- return stopped();
323
+ return awaitRun();
311
324
  }
312
325
  };
313
326
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btravstack/temporal-worker",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "The Temporal worker runtime for @btravstack/core: one unit per activity attempt, and a drain that honours the kernel's deadline",
5
5
  "keywords": [
6
6
  "graceful-shutdown",
@@ -54,6 +54,11 @@
54
54
  }
55
55
  },
56
56
  "devDependencies": {
57
+ "@btravstack/config": "0.15.0",
58
+ "@btravstack/core": "0.15.0",
59
+ "@btravstack/di": "0.15.0",
60
+ "@btravstack/internal-test-infra": "0.0.0",
61
+ "@btravstack/testing": "0.15.0",
57
62
  "@btravstack/tsconfig": "0.4.0",
58
63
  "@temporal-contract/client": "8.0.0-beta.9",
59
64
  "@temporal-contract/contract": "8.0.0-beta.9",
@@ -70,24 +75,19 @@
70
75
  "typescript": "7.0.2",
71
76
  "unthrown": "5.8.0",
72
77
  "vitest": "4.1.11",
73
- "zod": "4.5.4",
74
- "@btravstack/config": "0.14.0",
75
- "@btravstack/core": "0.14.0",
76
- "@btravstack/di": "0.14.0",
77
- "@btravstack/internal-test-infra": "0.0.0",
78
- "@btravstack/testing": "0.14.0"
78
+ "zod": "4.5.4"
79
79
  },
80
80
  "peerDependencies": {
81
+ "@btravstack/config": "^0.15.0",
82
+ "@btravstack/core": "^0.15.0",
83
+ "@btravstack/di": "^0.15.0",
81
84
  "@temporal-contract/client": "^8.0.0-beta.9",
82
85
  "@temporal-contract/contract": "^8.0.0-beta.9",
83
86
  "@temporal-contract/worker": "^8.0.0-beta.9",
84
87
  "@temporalio/activity": "^1.22.0",
85
88
  "@temporalio/common": "^1.22.0",
86
89
  "@temporalio/worker": "^1.22.0",
87
- "unthrown": "^5.0.0",
88
- "@btravstack/config": "^0.14.0",
89
- "@btravstack/core": "^0.14.0",
90
- "@btravstack/di": "^0.14.0"
90
+ "unthrown": "^5.0.0"
91
91
  },
92
92
  "peerDependenciesMeta": {
93
93
  "@temporal-contract/client": {
@@ -101,7 +101,6 @@
101
101
  "build": "tsdown src/index.ts src/schedule.ts --format cjs,esm --dts --clean",
102
102
  "dev": "tsdown src/index.ts src/schedule.ts --format cjs,esm --dts --watch",
103
103
  "test": "vitest run --coverage",
104
- "test:types": "tsc --noEmit -p tsconfig.test-d.json",
105
104
  "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test-d.json"
106
105
  }
107
106
  }