@btravstack/temporal-worker 0.15.0 → 0.16.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
@@ -151,7 +151,17 @@ const activityUnits = (host, observers, unit) => (invocation, next) => {
151
151
  *
152
152
  * The workflow id becomes the `traceId` — minted outside this process and steady
153
153
  * across every retry, so all attempts join up in a log. An activity with no
154
- * workflow falls back to the activity id.
154
+ * workflow falls back to the activity id; `workflowExecution` is optional
155
+ * because Temporal's own `Info` declares it so, "not set if the activity was
156
+ * not started by a Workflow", which a worker polling a task queue never sees.
157
+ *
158
+ * **A REUSED workflow id merges its runs into one trace**, and that is the
159
+ * trade rather than an oversight: Temporal allows an id again once the previous
160
+ * execution closed, so `order-42` run twice is one `traceId` over two runs.
161
+ * `runId` would separate them and is the wrong correlation for this transport —
162
+ * server-minted, opaque, and not what an operator greps for. A deployment that
163
+ * needs per-run traces gives its workflows unique ids, which is what a Schedule
164
+ * already does.
155
165
  */
156
166
  const metaFor = () => {
157
167
  const info = (0, _temporalio_activity.activityInfo)();
package/dist/index.mjs CHANGED
@@ -150,7 +150,17 @@ const activityUnits = (host, observers, unit) => (invocation, next) => {
150
150
  *
151
151
  * The workflow id becomes the `traceId` — minted outside this process and steady
152
152
  * across every retry, so all attempts join up in a log. An activity with no
153
- * workflow falls back to the activity id.
153
+ * workflow falls back to the activity id; `workflowExecution` is optional
154
+ * because Temporal's own `Info` declares it so, "not set if the activity was
155
+ * not started by a Workflow", which a worker polling a task queue never sees.
156
+ *
157
+ * **A REUSED workflow id merges its runs into one trace**, and that is the
158
+ * trade rather than an oversight: Temporal allows an id again once the previous
159
+ * execution closed, so `order-42` run twice is one `traceId` over two runs.
160
+ * `runId` would separate them and is the wrong correlation for this transport —
161
+ * server-minted, opaque, and not what an operator greps for. A deployment that
162
+ * needs per-run traces gives its workflows unique ids, which is what a Schedule
163
+ * already does.
154
164
  */
155
165
  const metaFor = () => {
156
166
  const info = activityInfo();
package/dist/schedule.cjs CHANGED
@@ -16,24 +16,29 @@ let _temporal_contract_client = require("@temporal-contract/client");
16
16
  * This recovers exactly that one error into an `update`. Every other error
17
17
  * stays on the channel, still typed.
18
18
  *
19
- * **`spec` is the only field reconciled**, and the rest of an existing
20
- * schedule is left as it stands. Two different reasons, and they are worth
21
- * telling apart:
19
+ * **`spec`, the action's `workflowType` and `args`, and `policies` are
20
+ * reconciled**; everything else about an existing schedule is left as it
21
+ * stands.
22
22
  *
23
+ * - **`args` and `workflowType` are written, and they are checked on the way
24
+ * through.** The typed handle's `update` validates the returned action's
25
+ * `args` against the named workflow's input schema before anything is
26
+ * persisted, and answers `WorkflowValidationError` — the same error `create`
27
+ * answers, already on this channel. So a deploy that changed what the
28
+ * workflow takes is either written or refused, never reported `"updated"`
29
+ * over a server still holding the old action. `workflowType` rides with them
30
+ * because it is what selects the schema those args are checked against.
23
31
  * - **`state` is deliberately preserved.** A schedule an operator paused stays
24
32
  * paused across a deploy, because unpausing it is a decision a person made
25
33
  * and a deploy is not the place to reverse it.
26
- * - **`args` and the rest of the action are preserved because this cannot
27
- * reconcile them SAFELY.** `create` validates `args` against the workflow's
28
- * input schema; the handle's `update` takes Temporal's own
29
- * `ScheduleUpdateOptions` and validates nothing, so writing them here would
30
- * push unvalidated input at the server through a door the typed client keeps
31
- * shut. A deploy that changes what a schedule RUNS — its args, its workflow,
32
- * its policies — should say so explicitly: delete the schedule and create it,
33
- * or reach `getHandle(id).update(...)` directly and own the shape.
34
+ * - **`memo`, `searchAttributes` and the action's own overrides are
35
+ * preserved**, because rebuilding the action wholesale means reproducing
36
+ * `create`'s own assembly here — the task queue off the contract, the search
37
+ * attribute translation, eight optional overrides — which is a copy that
38
+ * drifts. A deploy changing one of those deletes the schedule and creates it.
34
39
  *
35
- * So: after this call the schedule FIRES when the arguments say. What it fires
36
- * with is whatever it already fired with.
40
+ * So: after this call the schedule FIRES when the arguments say, and RUNS what
41
+ * they say.
37
42
  *
38
43
  * ```ts
39
44
  * await ensureSchedule(client.for(orderContract).schedule, "sweepStaleOrders", {
@@ -45,7 +50,13 @@ let _temporal_contract_client = require("@temporal-contract/client");
45
50
  */
46
51
  const ensureSchedule = (schedules, workflow, options) => schedules.create(workflow, options).map(() => "created").flatMapErrCases((matcher) => matcher.with(unthrown.P.tag(_temporal_contract_client.SCHEDULE_ALREADY_EXISTS_ERROR_TAG), () => schedules.getHandle(options.scheduleId).update((previous) => ({
47
52
  ...previous,
48
- spec: options.spec
53
+ spec: options.spec,
54
+ action: {
55
+ ...previous.action,
56
+ workflowType: workflow,
57
+ args: [options.args]
58
+ },
59
+ ...options.policies === void 0 ? {} : { policies: options.policies }
49
60
  })).map(() => "updated")).with(unthrown.P.tag("@temporal-contract/WorkflowNotInContractError"), (error) => (0, unthrown.ErrAsync)(error)).with(unthrown.P.tag("@temporal-contract/WorkflowValidationError"), (error) => (0, unthrown.ErrAsync)(error)));
50
61
  //#endregion
51
62
  exports.ensureSchedule = ensureSchedule;
@@ -18,24 +18,29 @@ export type ScheduleOutcome = "created" | "updated";
18
18
  * This recovers exactly that one error into an `update`. Every other error
19
19
  * stays on the channel, still typed.
20
20
  *
21
- * **`spec` is the only field reconciled**, and the rest of an existing
22
- * schedule is left as it stands. Two different reasons, and they are worth
23
- * telling apart:
21
+ * **`spec`, the action's `workflowType` and `args`, and `policies` are
22
+ * reconciled**; everything else about an existing schedule is left as it
23
+ * stands.
24
24
  *
25
+ * - **`args` and `workflowType` are written, and they are checked on the way
26
+ * through.** The typed handle's `update` validates the returned action's
27
+ * `args` against the named workflow's input schema before anything is
28
+ * persisted, and answers `WorkflowValidationError` — the same error `create`
29
+ * answers, already on this channel. So a deploy that changed what the
30
+ * workflow takes is either written or refused, never reported `"updated"`
31
+ * over a server still holding the old action. `workflowType` rides with them
32
+ * because it is what selects the schema those args are checked against.
25
33
  * - **`state` is deliberately preserved.** A schedule an operator paused stays
26
34
  * paused across a deploy, because unpausing it is a decision a person made
27
35
  * and a deploy is not the place to reverse it.
28
- * - **`args` and the rest of the action are preserved because this cannot
29
- * reconcile them SAFELY.** `create` validates `args` against the workflow's
30
- * input schema; the handle's `update` takes Temporal's own
31
- * `ScheduleUpdateOptions` and validates nothing, so writing them here would
32
- * push unvalidated input at the server through a door the typed client keeps
33
- * shut. A deploy that changes what a schedule RUNS — its args, its workflow,
34
- * its policies — should say so explicitly: delete the schedule and create it,
35
- * or reach `getHandle(id).update(...)` directly and own the shape.
36
+ * - **`memo`, `searchAttributes` and the action's own overrides are
37
+ * preserved**, because rebuilding the action wholesale means reproducing
38
+ * `create`'s own assembly here — the task queue off the contract, the search
39
+ * attribute translation, eight optional overrides — which is a copy that
40
+ * drifts. A deploy changing one of those deletes the schedule and creates it.
36
41
  *
37
- * So: after this call the schedule FIRES when the arguments say. What it fires
38
- * with is whatever it already fired with.
42
+ * So: after this call the schedule FIRES when the arguments say, and RUNS what
43
+ * they say.
39
44
  *
40
45
  * ```ts
41
46
  * await ensureSchedule(client.for(orderContract).schedule, "sweepStaleOrders", {
@@ -18,24 +18,29 @@ export type ScheduleOutcome = "created" | "updated";
18
18
  * This recovers exactly that one error into an `update`. Every other error
19
19
  * stays on the channel, still typed.
20
20
  *
21
- * **`spec` is the only field reconciled**, and the rest of an existing
22
- * schedule is left as it stands. Two different reasons, and they are worth
23
- * telling apart:
21
+ * **`spec`, the action's `workflowType` and `args`, and `policies` are
22
+ * reconciled**; everything else about an existing schedule is left as it
23
+ * stands.
24
24
  *
25
+ * - **`args` and `workflowType` are written, and they are checked on the way
26
+ * through.** The typed handle's `update` validates the returned action's
27
+ * `args` against the named workflow's input schema before anything is
28
+ * persisted, and answers `WorkflowValidationError` — the same error `create`
29
+ * answers, already on this channel. So a deploy that changed what the
30
+ * workflow takes is either written or refused, never reported `"updated"`
31
+ * over a server still holding the old action. `workflowType` rides with them
32
+ * because it is what selects the schema those args are checked against.
25
33
  * - **`state` is deliberately preserved.** A schedule an operator paused stays
26
34
  * paused across a deploy, because unpausing it is a decision a person made
27
35
  * and a deploy is not the place to reverse it.
28
- * - **`args` and the rest of the action are preserved because this cannot
29
- * reconcile them SAFELY.** `create` validates `args` against the workflow's
30
- * input schema; the handle's `update` takes Temporal's own
31
- * `ScheduleUpdateOptions` and validates nothing, so writing them here would
32
- * push unvalidated input at the server through a door the typed client keeps
33
- * shut. A deploy that changes what a schedule RUNS — its args, its workflow,
34
- * its policies — should say so explicitly: delete the schedule and create it,
35
- * or reach `getHandle(id).update(...)` directly and own the shape.
36
+ * - **`memo`, `searchAttributes` and the action's own overrides are
37
+ * preserved**, because rebuilding the action wholesale means reproducing
38
+ * `create`'s own assembly here — the task queue off the contract, the search
39
+ * attribute translation, eight optional overrides — which is a copy that
40
+ * drifts. A deploy changing one of those deletes the schedule and creates it.
36
41
  *
37
- * So: after this call the schedule FIRES when the arguments say. What it fires
38
- * with is whatever it already fired with.
42
+ * So: after this call the schedule FIRES when the arguments say, and RUNS what
43
+ * they say.
39
44
  *
40
45
  * ```ts
41
46
  * await ensureSchedule(client.for(orderContract).schedule, "sweepStaleOrders", {
package/dist/schedule.mjs CHANGED
@@ -15,24 +15,29 @@ import { SCHEDULE_ALREADY_EXISTS_ERROR_TAG } from "@temporal-contract/client";
15
15
  * This recovers exactly that one error into an `update`. Every other error
16
16
  * stays on the channel, still typed.
17
17
  *
18
- * **`spec` is the only field reconciled**, and the rest of an existing
19
- * schedule is left as it stands. Two different reasons, and they are worth
20
- * telling apart:
18
+ * **`spec`, the action's `workflowType` and `args`, and `policies` are
19
+ * reconciled**; everything else about an existing schedule is left as it
20
+ * stands.
21
21
  *
22
+ * - **`args` and `workflowType` are written, and they are checked on the way
23
+ * through.** The typed handle's `update` validates the returned action's
24
+ * `args` against the named workflow's input schema before anything is
25
+ * persisted, and answers `WorkflowValidationError` — the same error `create`
26
+ * answers, already on this channel. So a deploy that changed what the
27
+ * workflow takes is either written or refused, never reported `"updated"`
28
+ * over a server still holding the old action. `workflowType` rides with them
29
+ * because it is what selects the schema those args are checked against.
22
30
  * - **`state` is deliberately preserved.** A schedule an operator paused stays
23
31
  * paused across a deploy, because unpausing it is a decision a person made
24
32
  * and a deploy is not the place to reverse it.
25
- * - **`args` and the rest of the action are preserved because this cannot
26
- * reconcile them SAFELY.** `create` validates `args` against the workflow's
27
- * input schema; the handle's `update` takes Temporal's own
28
- * `ScheduleUpdateOptions` and validates nothing, so writing them here would
29
- * push unvalidated input at the server through a door the typed client keeps
30
- * shut. A deploy that changes what a schedule RUNS — its args, its workflow,
31
- * its policies — should say so explicitly: delete the schedule and create it,
32
- * or reach `getHandle(id).update(...)` directly and own the shape.
33
+ * - **`memo`, `searchAttributes` and the action's own overrides are
34
+ * preserved**, because rebuilding the action wholesale means reproducing
35
+ * `create`'s own assembly here — the task queue off the contract, the search
36
+ * attribute translation, eight optional overrides — which is a copy that
37
+ * drifts. A deploy changing one of those deletes the schedule and creates it.
33
38
  *
34
- * So: after this call the schedule FIRES when the arguments say. What it fires
35
- * with is whatever it already fired with.
39
+ * So: after this call the schedule FIRES when the arguments say, and RUNS what
40
+ * they say.
36
41
  *
37
42
  * ```ts
38
43
  * await ensureSchedule(client.for(orderContract).schedule, "sweepStaleOrders", {
@@ -44,7 +49,13 @@ import { SCHEDULE_ALREADY_EXISTS_ERROR_TAG } from "@temporal-contract/client";
44
49
  */
45
50
  const ensureSchedule = (schedules, workflow, options) => schedules.create(workflow, options).map(() => "created").flatMapErrCases((matcher) => matcher.with(P.tag(SCHEDULE_ALREADY_EXISTS_ERROR_TAG), () => schedules.getHandle(options.scheduleId).update((previous) => ({
46
51
  ...previous,
47
- spec: options.spec
52
+ spec: options.spec,
53
+ action: {
54
+ ...previous.action,
55
+ workflowType: workflow,
56
+ args: [options.args]
57
+ },
58
+ ...options.policies === void 0 ? {} : { policies: options.policies }
48
59
  })).map(() => "updated")).with(P.tag("@temporal-contract/WorkflowNotInContractError"), (error) => ErrAsync(error)).with(P.tag("@temporal-contract/WorkflowValidationError"), (error) => ErrAsync(error)));
49
60
  //#endregion
50
61
  export { ensureSchedule };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btravstack/temporal-worker",
3
- "version": "0.15.0",
3
+ "version": "0.16.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,11 +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",
57
+ "@btravstack/config": "0.16.0",
58
+ "@btravstack/core": "0.16.0",
59
+ "@btravstack/di": "0.16.0",
60
60
  "@btravstack/internal-test-infra": "0.0.0",
61
- "@btravstack/testing": "0.15.0",
61
+ "@btravstack/testing": "0.16.0",
62
62
  "@btravstack/tsconfig": "0.4.0",
63
63
  "@temporal-contract/client": "8.0.0-beta.9",
64
64
  "@temporal-contract/contract": "8.0.0-beta.9",
@@ -78,9 +78,9 @@
78
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
+ "@btravstack/config": "^0.16.0",
82
+ "@btravstack/core": "^0.16.0",
83
+ "@btravstack/di": "^0.16.0",
84
84
  "@temporal-contract/client": "^8.0.0-beta.9",
85
85
  "@temporal-contract/contract": "^8.0.0-beta.9",
86
86
  "@temporal-contract/worker": "^8.0.0-beta.9",