@temporalio/workflow 1.10.0 → 1.10.2

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.
@@ -11,7 +11,7 @@ export interface CancellationScopeOptions {
11
11
  /**
12
12
  * Time in milliseconds before the scope cancellation is automatically requested
13
13
  */
14
- timeout?: number;
14
+ timeout?: Duration;
15
15
  /**
16
16
  * If false, prevent outer cancellation from propagating to inner scopes, Activities, timers, and Triggers, defaults to true.
17
17
  * (Scope still propagates CancelledFailure thrown from within).
@@ -24,38 +24,56 @@ export interface CancellationScopeOptions {
24
24
  parent?: CancellationScope | typeof NO_PARENT;
25
25
  }
26
26
  /**
27
- * In the SDK, Workflows are represented internally by a tree of scopes where the `execute` function runs in the root scope.
28
- * Cancellation propagates from outer scopes to inner ones and is handled by catching {@link CancelledFailure}s
29
- * thrown by cancellable operations (see below).
27
+ * Cancellation Scopes provide the mechanic by which a Workflow may gracefully handle incoming requests for cancellation
28
+ * (e.g. in response to {@link WorkflowHandle.cancel} or through the UI or CLI), as well as request cancelation of
29
+ * cancellable operations it owns (e.g. Activities, Timers, Child Workflows, etc).
30
30
  *
31
- * Scopes are created using the `CancellationScope` constructor or the static helper methods
32
- * {@link cancellable}, {@link nonCancellable} and {@link withTimeout}.
31
+ * Cancellation Scopes form a tree, with the Workflow's main function running in the root scope of that tree.
32
+ * By default, cancellation propagates down from a parent scope to its children and its cancellable operations.
33
+ * A non-cancellable scope can receive cancellation requests, but is never effectively considered as cancelled,
34
+ * thus shieldding its children and cancellable operations from propagation of cancellation requests it receives.
33
35
  *
34
- * When a `CancellationScope` is cancelled, it will propagate cancellation any child scopes and any cancellable
35
- * operations created within it, such as:
36
+ * Scopes are created using the `CancellationScope` constructor or the static helper methods {@link cancellable},
37
+ * {@link nonCancellable} and {@link withTimeout}. `withTimeout` creates a scope that automatically cancels itself after
38
+ * some duration.
36
39
  *
37
- * - Activities
38
- * - Child Workflows
39
- * - Timers (created with the {@link sleep} function)
40
- * - {@link Trigger}s
41
- *
42
- * @example
40
+ * Cancellation of a cancellable scope results in all operations created directly in that scope to throw a
41
+ * {@link CancelledFailure} (either directly, or as the `cause` of an {@link ActivityFailure} or a
42
+ * {@link ChildWorkflowFailure}). Further attempt to create new cancellable scopes or cancellable operations within a
43
+ * scope that has already been cancelled will also immediately throw a {@link CancelledFailure} exception. It is however
44
+ * possible to create a non-cancellable scope at that point; this is often used to execute rollback or cleanup
45
+ * operations. For example:
43
46
  *
44
47
  * ```ts
45
- * await CancellationScope.cancellable(async () => {
46
- * const promise = someActivity();
47
- * CancellationScope.current().cancel(); // Cancels the activity
48
- * await promise; // Throws `ActivityFailure` with `cause` set to `CancelledFailure`
49
- * });
48
+ * async function myWorkflow(...): Promise<void> {
49
+ * try {
50
+ * // This activity runs in the root cancellation scope. Therefore, a cancelation request on
51
+ * // the Workflow execution (e.g. through the UI or CLI) automatically propagates to this
52
+ * // activity. Assuming that the activity properly handle the cancellation request, then the
53
+ * // call below will throw an `ActivityFailure` exception, with `cause` sets to an
54
+ * // instance of `CancelledFailure`.
55
+ * await someActivity();
56
+ * } catch (e) {
57
+ * if (isCancellation(e)) {
58
+ * // Run cleanup activity in a non-cancellable scope
59
+ * await CancellationScope.nonCancellable(async () => {
60
+ * await cleanupActivity();
61
+ * }
62
+ * } else {
63
+ * throw e;
64
+ * }
65
+ * }
66
+ * }
50
67
  * ```
51
68
  *
52
- * @example
69
+ * A cancellable scope may be programatically cancelled by calling {@link cancel|`scope.cancel()`}`. This may be used,
70
+ * for example, to explicitly request cancellation of an Activity or Child Workflow:
53
71
  *
54
72
  * ```ts
55
- * const scope = new CancellationScope();
56
- * const promise = scope.run(someActivity);
57
- * scope.cancel(); // Cancels the activity
58
- * await promise; // Throws `ActivityFailure` with `cause` set to `CancelledFailure`
73
+ * const cancellableActivityScope = new CancellationScope();
74
+ * const activityPromise = cancellableActivityScope.run(() => someActivity());
75
+ * cancellableActivityScope.cancel(); // Cancels the activity
76
+ * await activityPromise; // Throws `ActivityFailure` with `cause` set to `CancelledFailure`
59
77
  * ```
60
78
  */
61
79
  export declare class CancellationScope {
@@ -65,8 +83,13 @@ export declare class CancellationScope {
65
83
  */
66
84
  protected readonly timeout?: number;
67
85
  /**
68
- * If false, prevent outer cancellation from propagating to inner scopes, Activities, timers, and Triggers, defaults to true.
69
- * (Scope still propagates CancelledFailure thrown from within)
86
+ * If false, then this scope will never be considered cancelled, even if a cancellation request is received (either
87
+ * directly by calling `scope.cancel()` or indirectly by cancelling a cancellable parent scope). This effectively
88
+ * shields the scope's children and cancellable operations from propagation of cancellation requests made on the
89
+ * non-cancellable scope.
90
+ *
91
+ * Note that the Promise returned by the `run` function of non-cancellable scope may still throw a `CancelledFailure`
92
+ * if such an exception is thrown from within that scope (e.g. by directly cancelling a cancellable child scope).
70
93
  */
71
94
  readonly cancellable: boolean;
72
95
  /**
@@ -74,11 +97,19 @@ export declare class CancellationScope {
74
97
  */
75
98
  readonly parent?: CancellationScope;
76
99
  /**
77
- * Rejected when scope cancellation is requested
100
+ * A Promise that throws when a cancellable scope receives a cancellation request, either directly
101
+ * (i.e. `scope.cancel()`), or indirectly (by cancelling a cancellable parent scope).
102
+ *
103
+ * Note that a non-cancellable scope may receive cancellation requests, resulting in the `cancelRequested` promise for
104
+ * that scope to throw, though the scope will not effectively get cancelled (i.e. `consideredCancelled` will still
105
+ * return `false`, and cancellation will not be propagated to child scopes and contained operations).
78
106
  */
79
107
  readonly cancelRequested: Promise<never>;
80
108
  protected readonly reject: (reason?: any) => void;
81
109
  constructor(options?: CancellationScopeOptions);
110
+ /**
111
+ * Whether the scope was effectively cancelled. A non-cancellable scope can never be considered cancelled.
112
+ */
82
113
  get consideredCancelled(): boolean;
83
114
  /**
84
115
  * Activate the scope as current and run `fn`
@@ -108,7 +139,7 @@ export declare class CancellationScope {
108
139
  /** Alias to `new CancellationScope({ cancellable: false }).run(fn)` */
109
140
  static nonCancellable<T>(fn: () => Promise<T>): Promise<T>;
110
141
  /** Alias to `new CancellationScope({ cancellable: true, timeout }).run(fn)` */
111
- static withTimeout<T>(timeout: number, fn: () => Promise<T>): Promise<T>;
142
+ static withTimeout<T>(timeout: Duration, fn: () => Promise<T>): Promise<T>;
112
143
  }
113
144
  /**
114
145
  * Avoid exposing the storage directly so it doesn't get frozen
@@ -14,7 +14,10 @@ var _CancellationScope_cancelRequested;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.registerSleepImplementation = exports.RootCancellationScope = exports.disableStorage = exports.CancellationScope = exports.AsyncLocalStorage = void 0;
16
16
  const common_1 = require("@temporalio/common");
17
+ const time_1 = require("@temporalio/common/lib/time");
17
18
  const stack_helpers_1 = require("./stack-helpers");
19
+ const global_attributes_1 = require("./global-attributes");
20
+ const flags_1 = require("./flags");
18
21
  // AsyncLocalStorage is injected via vm module into global scope.
19
22
  // In case Workflow code is imported in Node.js context, replace with an empty class.
20
23
  exports.AsyncLocalStorage = globalThis.AsyncLocalStorage ?? class {
@@ -22,49 +25,65 @@ exports.AsyncLocalStorage = globalThis.AsyncLocalStorage ?? class {
22
25
  /** Magic symbol used to create the root scope - intentionally not exported */
23
26
  const NO_PARENT = Symbol('NO_PARENT');
24
27
  /**
25
- * In the SDK, Workflows are represented internally by a tree of scopes where the `execute` function runs in the root scope.
26
- * Cancellation propagates from outer scopes to inner ones and is handled by catching {@link CancelledFailure}s
27
- * thrown by cancellable operations (see below).
28
+ * Cancellation Scopes provide the mechanic by which a Workflow may gracefully handle incoming requests for cancellation
29
+ * (e.g. in response to {@link WorkflowHandle.cancel} or through the UI or CLI), as well as request cancelation of
30
+ * cancellable operations it owns (e.g. Activities, Timers, Child Workflows, etc).
28
31
  *
29
- * Scopes are created using the `CancellationScope` constructor or the static helper methods
30
- * {@link cancellable}, {@link nonCancellable} and {@link withTimeout}.
32
+ * Cancellation Scopes form a tree, with the Workflow's main function running in the root scope of that tree.
33
+ * By default, cancellation propagates down from a parent scope to its children and its cancellable operations.
34
+ * A non-cancellable scope can receive cancellation requests, but is never effectively considered as cancelled,
35
+ * thus shieldding its children and cancellable operations from propagation of cancellation requests it receives.
31
36
  *
32
- * When a `CancellationScope` is cancelled, it will propagate cancellation any child scopes and any cancellable
33
- * operations created within it, such as:
37
+ * Scopes are created using the `CancellationScope` constructor or the static helper methods {@link cancellable},
38
+ * {@link nonCancellable} and {@link withTimeout}. `withTimeout` creates a scope that automatically cancels itself after
39
+ * some duration.
34
40
  *
35
- * - Activities
36
- * - Child Workflows
37
- * - Timers (created with the {@link sleep} function)
38
- * - {@link Trigger}s
39
- *
40
- * @example
41
+ * Cancellation of a cancellable scope results in all operations created directly in that scope to throw a
42
+ * {@link CancelledFailure} (either directly, or as the `cause` of an {@link ActivityFailure} or a
43
+ * {@link ChildWorkflowFailure}). Further attempt to create new cancellable scopes or cancellable operations within a
44
+ * scope that has already been cancelled will also immediately throw a {@link CancelledFailure} exception. It is however
45
+ * possible to create a non-cancellable scope at that point; this is often used to execute rollback or cleanup
46
+ * operations. For example:
41
47
  *
42
48
  * ```ts
43
- * await CancellationScope.cancellable(async () => {
44
- * const promise = someActivity();
45
- * CancellationScope.current().cancel(); // Cancels the activity
46
- * await promise; // Throws `ActivityFailure` with `cause` set to `CancelledFailure`
47
- * });
49
+ * async function myWorkflow(...): Promise<void> {
50
+ * try {
51
+ * // This activity runs in the root cancellation scope. Therefore, a cancelation request on
52
+ * // the Workflow execution (e.g. through the UI or CLI) automatically propagates to this
53
+ * // activity. Assuming that the activity properly handle the cancellation request, then the
54
+ * // call below will throw an `ActivityFailure` exception, with `cause` sets to an
55
+ * // instance of `CancelledFailure`.
56
+ * await someActivity();
57
+ * } catch (e) {
58
+ * if (isCancellation(e)) {
59
+ * // Run cleanup activity in a non-cancellable scope
60
+ * await CancellationScope.nonCancellable(async () => {
61
+ * await cleanupActivity();
62
+ * }
63
+ * } else {
64
+ * throw e;
65
+ * }
66
+ * }
67
+ * }
48
68
  * ```
49
69
  *
50
- * @example
70
+ * A cancellable scope may be programatically cancelled by calling {@link cancel|`scope.cancel()`}`. This may be used,
71
+ * for example, to explicitly request cancellation of an Activity or Child Workflow:
51
72
  *
52
73
  * ```ts
53
- * const scope = new CancellationScope();
54
- * const promise = scope.run(someActivity);
55
- * scope.cancel(); // Cancels the activity
56
- * await promise; // Throws `ActivityFailure` with `cause` set to `CancelledFailure`
74
+ * const cancellableActivityScope = new CancellationScope();
75
+ * const activityPromise = cancellableActivityScope.run(() => someActivity());
76
+ * cancellableActivityScope.cancel(); // Cancels the activity
77
+ * await activityPromise; // Throws `ActivityFailure` with `cause` set to `CancelledFailure`
57
78
  * ```
58
79
  */
59
80
  class CancellationScope {
60
81
  constructor(options) {
61
82
  _CancellationScope_cancelRequested.set(this, false);
62
- this.timeout = options?.timeout;
83
+ this.timeout = (0, time_1.msOptionalToNumber)(options?.timeout);
63
84
  this.cancellable = options?.cancellable ?? true;
64
85
  this.cancelRequested = new Promise((_, reject) => {
65
- // Typescript does not understand that the Promise executor runs synchronously
66
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
67
- // @ts-ignore
86
+ // @ts-expect-error TSC doesn't understand that the Promise executor runs synchronously
68
87
  this.reject = (err) => {
69
88
  __classPrivateFieldSet(this, _CancellationScope_cancelRequested, true, "f");
70
89
  reject(err);
@@ -75,12 +94,26 @@ class CancellationScope {
75
94
  (0, stack_helpers_1.untrackPromise)(this.cancelRequested.catch(() => undefined));
76
95
  if (options?.parent !== NO_PARENT) {
77
96
  this.parent = options?.parent || CancellationScope.current();
78
- __classPrivateFieldSet(this, _CancellationScope_cancelRequested, __classPrivateFieldGet(this.parent, _CancellationScope_cancelRequested, "f"), "f");
79
- this.parent.cancelRequested.catch((err) => {
80
- this.reject(err);
81
- });
97
+ if (this.parent.cancellable ||
98
+ (__classPrivateFieldGet(this.parent, _CancellationScope_cancelRequested, "f") &&
99
+ !(0, global_attributes_1.getActivator)().hasFlag(flags_1.SdkFlags.NonCancellableScopesAreShieldedFromPropagation))) {
100
+ __classPrivateFieldSet(this, _CancellationScope_cancelRequested, __classPrivateFieldGet(this.parent, _CancellationScope_cancelRequested, "f"), "f");
101
+ (0, stack_helpers_1.untrackPromise)(this.parent.cancelRequested.catch((err) => {
102
+ this.reject(err);
103
+ }));
104
+ }
105
+ else {
106
+ (0, stack_helpers_1.untrackPromise)(this.parent.cancelRequested.catch((err) => {
107
+ if (!(0, global_attributes_1.getActivator)().hasFlag(flags_1.SdkFlags.NonCancellableScopesAreShieldedFromPropagation)) {
108
+ this.reject(err);
109
+ }
110
+ }));
111
+ }
82
112
  }
83
113
  }
114
+ /**
115
+ * Whether the scope was effectively cancelled. A non-cancellable scope can never be considered cancelled.
116
+ */
84
117
  get consideredCancelled() {
85
118
  return __classPrivateFieldGet(this, _CancellationScope_cancelRequested, "f") && this.cancellable;
86
119
  }
@@ -101,12 +134,25 @@ class CancellationScope {
101
134
  * Could have been written as anonymous function, made into a method for improved stack traces.
102
135
  */
103
136
  async runInContext(fn) {
137
+ let timerScope;
104
138
  if (this.timeout) {
105
- (0, stack_helpers_1.untrackPromise)(sleep(this.timeout).then(() => this.cancel(), () => {
139
+ timerScope = new CancellationScope();
140
+ (0, stack_helpers_1.untrackPromise)(timerScope
141
+ .run(() => sleep(this.timeout))
142
+ .then(() => this.cancel(), () => {
106
143
  // scope was already cancelled, ignore
107
144
  }));
108
145
  }
109
- return await fn();
146
+ try {
147
+ return await fn();
148
+ }
149
+ finally {
150
+ if (timerScope &&
151
+ !timerScope.consideredCancelled &&
152
+ (0, global_attributes_1.getActivator)().hasFlag(flags_1.SdkFlags.NonCancellableScopesAreShieldedFromPropagation)) {
153
+ timerScope.cancel();
154
+ }
155
+ }
110
156
  }
111
157
  /**
112
158
  * Request to cancel the scope and linked children
@@ -1 +1 @@
1
- {"version":3,"file":"cancellation-scope.js","sourceRoot":"","sources":["../src/cancellation-scope.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,+CAAmF;AACnF,mDAAiD;AAEjD,iEAAiE;AACjE,qFAAqF;AACxE,QAAA,iBAAiB,GAAyB,UAAkB,CAAC,iBAAiB,IAAI;CAAQ,CAAC;AAExG,8EAA8E;AAC9E,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAuBtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAa,iBAAiB;IA4B5B,YAAY,OAAkC;QAP9C,6CAAmB,KAAK,EAAC;QAQvB,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,IAAI,CAAC;QAChD,IAAI,CAAC,eAAe,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;YAC/C,8EAA8E;YAC9E,6DAA6D;YAC7D,aAAa;YACb,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE,EAAE;gBACpB,uBAAA,IAAI,sCAAoB,IAAI,MAAA,CAAC;gBAC7B,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,IAAA,8BAAc,EAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACrC,6BAA6B;QAC7B,IAAA,8BAAc,EAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5D,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,iBAAiB,CAAC,OAAO,EAAE,CAAC;YAC7D,uBAAA,IAAI,sCAAoB,uBAAA,IAAI,CAAC,MAAM,0CAAiB,MAAA,CAAC;YACrD,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACxC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAW,mBAAmB;QAC5B,OAAO,uBAAA,IAAI,0CAAiB,IAAI,IAAI,CAAC,WAAW,CAAC;IACnD,CAAC;IACD;;;;;;;OAOG;IACH,GAAG,CAAI,EAAoB;QACzB,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAqB,CAAC,CAAC;IACjF,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,YAAY,CAAI,EAAoB;QAClD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAA,8BAAc,EACZ,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CACtB,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EACnB,GAAG,EAAE;gBACH,sCAAsC;YACxC,CAAC,CACF,CACF,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,IAAI,CAAC,MAAM,CAAC,IAAI,yBAAgB,CAAC,8BAA8B,CAAC,CAAC,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAO;QACZ,+EAA+E;QAC/E,OAAO,OAAO,CAAC,QAAQ,EAAE,IAAK,UAAkB,CAAC,sBAAsB,CAAC,SAAS,CAAC;IACpF,CAAC;IAED,sEAAsE;IACtE,MAAM,CAAC,WAAW,CAAI,EAAoB;QACxC,OAAO,IAAI,IAAI,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,uEAAuE;IACvE,MAAM,CAAC,cAAc,CAAI,EAAoB;QAC3C,OAAO,IAAI,IAAI,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,+EAA+E;IAC/E,MAAM,CAAC,WAAW,CAAI,OAAe,EAAE,EAAoB;QACzD,OAAO,IAAI,IAAI,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC;CACF;AAnHD,8CAmHC;;AAED,MAAM,OAAO,GAAG,IAAI,yBAAiB,EAAqB,CAAC;AAE3D;;GAEG;AACH,SAAgB,cAAc;IAC5B,OAAO,CAAC,OAAO,EAAE,CAAC;AACpB,CAAC;AAFD,wCAEC;AAED,MAAa,qBAAsB,SAAQ,iBAAiB;IAC1D;QACE,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,MAAM,CAAC,IAAI,yBAAgB,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC1D,CAAC;CACF;AARD,sDAQC;AAED,+FAA+F;AAC/F,IAAI,KAAK,GAAG,CAAC,CAAW,EAAiB,EAAE;IACzC,MAAM,IAAI,0BAAiB,CAAC,4CAA4C,CAAC,CAAC;AAC5E,CAAC,CAAC;AAEF,SAAgB,2BAA2B,CAAC,EAAgB;IAC1D,KAAK,GAAG,EAAE,CAAC;AACb,CAAC;AAFD,kEAEC"}
1
+ {"version":3,"file":"cancellation-scope.js","sourceRoot":"","sources":["../src/cancellation-scope.ts"],"names":[],"mappings":"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"}
package/lib/flags.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export type SdkFlag = {
2
+ get id(): number;
3
+ get default(): boolean;
4
+ };
5
+ export declare const SdkFlags: {
6
+ /**
7
+ * This flag gates multiple fixes related to cancellation scopes and timers introduced in 1.10.2/1.11.0:
8
+ * - Cancellation of a non-cancellable scope no longer propagates to children scopes
9
+ * (see https://github.com/temporalio/sdk-typescript/issues/1423).
10
+ * - CancellationScope.withTimeout(fn) now cancel the timer if `fn` completes before expiration
11
+ * of the timeout, similar to how `condition(fn, timeout)` works.
12
+ * - Timers created using setTimeout can now be intercepted.
13
+ *
14
+ * @since Introduced in 1.10.2/1.11.0.
15
+ */
16
+ readonly NonCancellableScopesAreShieldedFromPropagation: SdkFlag;
17
+ };
18
+ export declare function assertValidFlag(id: number): void;
package/lib/flags.js ADDED
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertValidFlag = exports.SdkFlags = void 0;
4
+ const flagsRegistry = new Map();
5
+ exports.SdkFlags = {
6
+ /**
7
+ * This flag gates multiple fixes related to cancellation scopes and timers introduced in 1.10.2/1.11.0:
8
+ * - Cancellation of a non-cancellable scope no longer propagates to children scopes
9
+ * (see https://github.com/temporalio/sdk-typescript/issues/1423).
10
+ * - CancellationScope.withTimeout(fn) now cancel the timer if `fn` completes before expiration
11
+ * of the timeout, similar to how `condition(fn, timeout)` works.
12
+ * - Timers created using setTimeout can now be intercepted.
13
+ *
14
+ * @since Introduced in 1.10.2/1.11.0.
15
+ */
16
+ NonCancellableScopesAreShieldedFromPropagation: defineFlag(1, false),
17
+ };
18
+ function defineFlag(id, def) {
19
+ const flag = { id, default: def };
20
+ flagsRegistry.set(id, flag);
21
+ return flag;
22
+ }
23
+ function assertValidFlag(id) {
24
+ if (!flagsRegistry.has(id))
25
+ throw new TypeError(`Unknown SDK flag: ${id}`);
26
+ }
27
+ exports.assertValidFlag = assertValidFlag;
28
+ //# sourceMappingURL=flags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":";;;AAKA,MAAM,aAAa,GAAyB,IAAI,GAAG,EAAE,CAAC;AAEzC,QAAA,QAAQ,GAAG;IACtB;;;;;;;;;OASG;IACH,8CAA8C,EAAE,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC;CAC5D,CAAC;AAEX,SAAS,UAAU,CAAC,EAAU,EAAE,GAAY;IAC1C,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAClC,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,eAAe,CAAC,EAAU;IACxC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;AAC7E,CAAC;AAFD,0CAEC"}
@@ -0,0 +1 @@
1
+ export declare function overrideGlobals(): void;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.overrideGlobals = void 0;
4
+ /**
5
+ * Overrides some global objects to make them deterministic.
6
+ *
7
+ * @module
8
+ */
9
+ const time_1 = require("@temporalio/common/lib/time");
10
+ const cancellation_scope_1 = require("./cancellation-scope");
11
+ const errors_1 = require("./errors");
12
+ const global_attributes_1 = require("./global-attributes");
13
+ const flags_1 = require("./flags");
14
+ const workflow_1 = require("./workflow");
15
+ const stack_helpers_1 = require("./stack-helpers");
16
+ const global = globalThis;
17
+ const OriginalDate = globalThis.Date;
18
+ function overrideGlobals() {
19
+ // Mock any weak reference because GC is non-deterministic and the effect is observable from the Workflow.
20
+ // Workflow developer will get a meaningful exception if they try to use these.
21
+ global.WeakRef = function () {
22
+ throw new errors_1.DeterminismViolationError('WeakRef cannot be used in Workflows because v8 GC is non-deterministic');
23
+ };
24
+ global.FinalizationRegistry = function () {
25
+ throw new errors_1.DeterminismViolationError('FinalizationRegistry cannot be used in Workflows because v8 GC is non-deterministic');
26
+ };
27
+ global.Date = function (...args) {
28
+ if (args.length > 0) {
29
+ return new OriginalDate(...args);
30
+ }
31
+ return new OriginalDate((0, global_attributes_1.getActivator)().now);
32
+ };
33
+ global.Date.now = function () {
34
+ return (0, global_attributes_1.getActivator)().now;
35
+ };
36
+ global.Date.parse = OriginalDate.parse.bind(OriginalDate);
37
+ global.Date.UTC = OriginalDate.UTC.bind(OriginalDate);
38
+ global.Date.prototype = OriginalDate.prototype;
39
+ const timeoutCancelationScopes = new Map();
40
+ /**
41
+ * @param ms sleep duration - number of milliseconds. If given a negative number, value will be set to 1.
42
+ */
43
+ global.setTimeout = function (cb, ms, ...args) {
44
+ ms = Math.max(1, ms);
45
+ const activator = (0, global_attributes_1.getActivator)();
46
+ if (activator.hasFlag(flags_1.SdkFlags.NonCancellableScopesAreShieldedFromPropagation)) {
47
+ // Capture the sequence number that sleep will allocate
48
+ const seq = activator.nextSeqs.timer;
49
+ const timerScope = new cancellation_scope_1.CancellationScope({ cancellable: true });
50
+ const sleepPromise = timerScope.run(() => (0, workflow_1.sleep)(ms));
51
+ sleepPromise.then(() => {
52
+ timeoutCancelationScopes.delete(seq);
53
+ cb(...args);
54
+ }, () => {
55
+ timeoutCancelationScopes.delete(seq);
56
+ });
57
+ (0, stack_helpers_1.untrackPromise)(sleepPromise);
58
+ timeoutCancelationScopes.set(seq, timerScope);
59
+ return seq;
60
+ }
61
+ else {
62
+ const seq = activator.nextSeqs.timer++;
63
+ // Create a Promise for AsyncLocalStorage to be able to track this completion using promise hooks.
64
+ new Promise((resolve, reject) => {
65
+ activator.completions.timer.set(seq, { resolve, reject });
66
+ activator.pushCommand({
67
+ startTimer: {
68
+ seq,
69
+ startToFireTimeout: (0, time_1.msToTs)(ms),
70
+ },
71
+ });
72
+ }).then(() => cb(...args), () => undefined /* ignore cancellation */);
73
+ return seq;
74
+ }
75
+ };
76
+ global.clearTimeout = function (handle) {
77
+ const activator = (0, global_attributes_1.getActivator)();
78
+ const timerScope = timeoutCancelationScopes.get(handle);
79
+ if (timerScope) {
80
+ timeoutCancelationScopes.delete(handle);
81
+ timerScope.cancel();
82
+ }
83
+ else {
84
+ activator.nextSeqs.timer++; // Shouldn't increase seq number, but that's the legacy behavior
85
+ activator.completions.timer.delete(handle);
86
+ activator.pushCommand({
87
+ cancelTimer: {
88
+ seq: handle,
89
+ },
90
+ });
91
+ }
92
+ };
93
+ // activator.random is mutable, don't hardcode its reference
94
+ Math.random = () => (0, global_attributes_1.getActivator)().random();
95
+ }
96
+ exports.overrideGlobals = overrideGlobals;
97
+ //# sourceMappingURL=global-overrides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-overrides.js","sourceRoot":"","sources":["../src/global-overrides.ts"],"names":[],"mappings":"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"}
@@ -397,3 +397,7 @@ export type UpdateHandlerOptions<Args extends any[]> = {
397
397
  validator?: UpdateValidator<Args>;
398
398
  description?: string;
399
399
  };
400
+ export interface ActivationCompletion {
401
+ commands: coresdk.workflow_commands.IWorkflowCommand[];
402
+ usedInternalFlags: number[];
403
+ }
@@ -4,8 +4,9 @@ import type { coresdk } from '@temporalio/proto';
4
4
  import { RNG } from './alea';
5
5
  import { RootCancellationScope } from './cancellation-scope';
6
6
  import { QueryInput, SignalInput, UpdateInput, WorkflowExecuteInput, WorkflowInterceptors } from './interceptors';
7
- import { DefaultSignalHandler, FileLocation, WorkflowInfo, WorkflowCreateOptionsInternal } from './interfaces';
7
+ import { DefaultSignalHandler, FileLocation, WorkflowInfo, WorkflowCreateOptionsInternal, ActivationCompletion } from './interfaces';
8
8
  import { type SinkCall } from './sinks';
9
+ import { SdkFlag } from './flags';
9
10
  export interface Stack {
10
11
  formatted: string;
11
12
  structured: FileLocation[];
@@ -158,11 +159,12 @@ export declare class Activator implements ActivationHandler {
158
159
  /**
159
160
  * Patches we know the status of for this workflow, as in {@link patched}
160
161
  */
161
- readonly knownPresentPatches: Set<string>;
162
+ private readonly knownPresentPatches;
162
163
  /**
163
164
  * Patches we sent to core {@link patched}
164
165
  */
165
- readonly sentPatches: Set<string>;
166
+ private readonly sentPatches;
167
+ private readonly knownFlags;
166
168
  /**
167
169
  * Buffered sink calls per activation
168
170
  */
@@ -182,7 +184,7 @@ export declare class Activator implements ActivationHandler {
182
184
  * Prevents commands from being added after Workflow completion.
183
185
  */
184
186
  pushCommand(cmd: coresdk.workflow_commands.IWorkflowCommand, complete?: boolean): void;
185
- getAndResetCommands(): coresdk.workflow_commands.IWorkflowCommand[];
187
+ concludeActivation(): ActivationCompletion;
186
188
  startWorkflowNextHandler({ args }: WorkflowExecuteInput): Promise<any>;
187
189
  startWorkflow(activation: coresdk.workflow_activation.IStartWorkflow): void;
188
190
  cancelWorkflow(_activation: coresdk.workflow_activation.ICancelWorkflow): void;
@@ -204,6 +206,9 @@ export declare class Activator implements ActivationHandler {
204
206
  resolveRequestCancelExternalWorkflow(activation: coresdk.workflow_activation.IResolveRequestCancelExternalWorkflow): void;
205
207
  updateRandomSeed(activation: coresdk.workflow_activation.IUpdateRandomSeed): void;
206
208
  notifyHasPatch(activation: coresdk.workflow_activation.INotifyHasPatch): void;
209
+ patchInternal(patchId: string, deprecated: boolean): boolean;
210
+ addKnownFlags(flags: number[]): void;
211
+ hasFlag(flag: SdkFlag): boolean;
207
212
  removeFromCache(): void;
208
213
  /**
209
214
  * Transforms failures into a command to be sent to the server.
package/lib/internals.js CHANGED
@@ -14,6 +14,7 @@ const interfaces_1 = require("./interfaces");
14
14
  const stack_helpers_1 = require("./stack-helpers");
15
15
  const pkg_1 = __importDefault(require("./pkg"));
16
16
  const logs_1 = require("./logs");
17
+ const flags_1 = require("./flags");
17
18
  var StartChildWorkflowExecutionFailedCause;
18
19
  (function (StartChildWorkflowExecutionFailedCause) {
19
20
  StartChildWorkflowExecutionFailedCause[StartChildWorkflowExecutionFailedCause["START_CHILD_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED"] = 0] = "START_CHILD_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED";
@@ -201,6 +202,7 @@ class Activator {
201
202
  * Patches we sent to core {@link patched}
202
203
  */
203
204
  this.sentPatches = new Set();
205
+ this.knownFlags = new Set();
204
206
  /**
205
207
  * Buffered sink calls per activation
206
208
  */
@@ -262,10 +264,11 @@ class Activator {
262
264
  this.completed = true;
263
265
  }
264
266
  }
265
- getAndResetCommands() {
266
- const commands = this.commands;
267
- this.commands = [];
268
- return commands;
267
+ concludeActivation() {
268
+ return {
269
+ commands: this.commands.splice(0),
270
+ usedInternalFlags: [...this.knownFlags],
271
+ };
269
272
  }
270
273
  async startWorkflowNextHandler({ args }) {
271
274
  const { workflow } = this;
@@ -598,6 +601,38 @@ class Activator {
598
601
  }
599
602
  this.knownPresentPatches.add(activation.patchId);
600
603
  }
604
+ patchInternal(patchId, deprecated) {
605
+ if (this.workflow === undefined) {
606
+ throw new common_1.IllegalStateError('Patches cannot be used before Workflow starts');
607
+ }
608
+ const usePatch = !this.info.unsafe.isReplaying || this.knownPresentPatches.has(patchId);
609
+ // Avoid sending commands for patches core already knows about.
610
+ // This optimization enables development of automatic patching tools.
611
+ if (usePatch && !this.sentPatches.has(patchId)) {
612
+ this.pushCommand({
613
+ setPatchMarker: { patchId, deprecated },
614
+ });
615
+ this.sentPatches.add(patchId);
616
+ }
617
+ return usePatch;
618
+ }
619
+ // Called early while handling an activation to register known flags
620
+ addKnownFlags(flags) {
621
+ for (const flag of flags) {
622
+ (0, flags_1.assertValidFlag)(flag);
623
+ this.knownFlags.add(flag);
624
+ }
625
+ }
626
+ hasFlag(flag) {
627
+ if (this.knownFlags.has(flag.id)) {
628
+ return true;
629
+ }
630
+ if (!this.info.unsafe.isReplaying && flag.default) {
631
+ this.knownFlags.add(flag.id);
632
+ return true;
633
+ }
634
+ return false;
635
+ }
601
636
  removeFromCache() {
602
637
  throw new common_1.IllegalStateError('removeFromCache activation job should not reach workflow');
603
638
  }