@lostgradient/weft 0.7.0 → 0.9.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 (141) hide show
  1. package/README.md +9 -3
  2. package/dist/cli/generated/operation-client.generated.d.ts +1 -0
  3. package/dist/cli-main.js +78 -78
  4. package/dist/core/context/activity-retry-state.d.ts +6 -5
  5. package/dist/core/context/activity-retry-state.js +31 -21
  6. package/dist/core/context/durable-activity.d.ts +117 -0
  7. package/dist/core/context/durable-activity.js +79 -0
  8. package/dist/core/context/durable-operations.js +1 -1
  9. package/dist/core/context/index.d.ts +1 -0
  10. package/dist/core/context/index.js +2 -0
  11. package/dist/core/context/operation-request.d.ts +17 -0
  12. package/dist/core/context/parallel-operations.js +1 -0
  13. package/dist/core/context/run-operation-cached-request.d.ts +8 -0
  14. package/dist/core/context/run-operation-cached-request.js +59 -0
  15. package/dist/core/context/run-operation.d.ts +23 -5
  16. package/dist/core/context/run-operation.js +63 -47
  17. package/dist/core/context/speculative-child.js +1 -0
  18. package/dist/core/context/types.d.ts +1 -0
  19. package/dist/core/engine/activity-heartbeat-tracking.d.ts +8 -17
  20. package/dist/core/engine/activity-heartbeat-tracking.js +12 -2
  21. package/dist/core/engine/activity-reconciliation.d.ts +1 -0
  22. package/dist/core/engine/activity-reconciliation.js +7 -2
  23. package/dist/core/engine/anonymous-signal-sequence.js +6 -6
  24. package/dist/core/engine/async-activity-completion.d.ts +5 -7
  25. package/dist/core/engine/async-activity-completion.js +13 -9
  26. package/dist/core/engine/bulk-operations-purge.js +2 -1
  27. package/dist/core/engine/bulk-operations.js +18 -36
  28. package/dist/core/engine/callback-checkpoint-persistence.d.ts +3 -0
  29. package/dist/core/engine/callback-checkpoint-persistence.js +25 -0
  30. package/dist/core/engine/callback-creators-bundles.js +5 -2
  31. package/dist/core/engine/checkpoint-io.d.ts +4 -1
  32. package/dist/core/engine/checkpoint-io.js +19 -10
  33. package/dist/core/engine/completed-review-storage.d.ts +2 -1
  34. package/dist/core/engine/completed-review-storage.js +4 -3
  35. package/dist/core/engine/disposal.js +1 -0
  36. package/dist/core/engine/engine-internal-types.d.ts +1 -0
  37. package/dist/core/engine/index.d.ts +31 -0
  38. package/dist/core/engine/index.js +19 -10
  39. package/dist/core/engine/inline-launch-queue.js +1 -1
  40. package/dist/core/engine/internals.d.ts +25 -2
  41. package/dist/core/engine/lease-manager.js +2 -2
  42. package/dist/core/engine/lifecycle/fork-helpers.js +1 -0
  43. package/dist/core/engine/lifecycle/resume.js +6 -0
  44. package/dist/core/engine/lifecycle/start-exec.d.ts +2 -2
  45. package/dist/core/engine/lifecycle/start-exec.js +6 -4
  46. package/dist/core/engine/lifecycle/start.js +1 -0
  47. package/dist/core/engine/lifecycle/transition.js +6 -0
  48. package/dist/core/engine/memo-durable-activity.d.ts +11 -0
  49. package/dist/core/engine/memo-durable-activity.js +282 -0
  50. package/dist/core/engine/operations-activity.d.ts +6 -2
  51. package/dist/core/engine/operations-activity.js +24 -10
  52. package/dist/core/engine/operations-data.d.ts +4 -1
  53. package/dist/core/engine/operations-data.js +3 -3
  54. package/dist/core/engine/operations-time.d.ts +2 -2
  55. package/dist/core/engine/operations-time.js +40 -6
  56. package/dist/core/engine/reviews.js +7 -4
  57. package/dist/core/engine/schedule-timer.js +2 -0
  58. package/dist/core/engine/schedules.js +3 -0
  59. package/dist/core/engine/storage-io.js +1 -1
  60. package/dist/core/engine/termination/cleanup.js +15 -13
  61. package/dist/core/engine/termination/finalizer-activity.d.ts +1 -1
  62. package/dist/core/engine/termination/finalizer-activity.js +5 -1
  63. package/dist/core/engine/termination/finalizer.js +1 -1
  64. package/dist/core/engine/validation/schedule-options.d.ts +9 -0
  65. package/dist/core/engine/validation/schedule-options.js +59 -0
  66. package/dist/core/engine/validation/schedule.d.ts +3 -8
  67. package/dist/core/engine/validation/schedule.js +40 -56
  68. package/dist/core/engine/validation.js +1 -0
  69. package/dist/core/execution-strategy.d.ts +1 -0
  70. package/dist/core/inline-execution-strategy.context-options.d.ts +1 -0
  71. package/dist/core/inline-execution-strategy.context-options.js +3 -0
  72. package/dist/core/json.js +1 -1
  73. package/dist/core/types/activity.d.ts +11 -0
  74. package/dist/core/types/checkpoint.d.ts +1 -0
  75. package/dist/core/types/schedules.d.ts +10 -0
  76. package/dist/core/types/state.d.ts +6 -0
  77. package/dist/core/types/workflow-context.d.ts +13 -0
  78. package/dist/core/weft-error.d.ts +1 -1
  79. package/dist/core/weft-error.js +2 -0
  80. package/dist/core/worker-execution-strategy.d.ts +1 -0
  81. package/dist/core/worker-inbound-message.d.ts +1 -0
  82. package/dist/core/worker-inbound-message.js +3 -0
  83. package/dist/index.d.ts +2 -1
  84. package/dist/index.js +6 -0
  85. package/dist/json-schema.js +2 -2
  86. package/dist/mcp/cli.js +32 -32
  87. package/dist/observability/index.js +2 -2
  88. package/dist/runtime/portable.d.ts +1 -1
  89. package/dist/server/handler.js +27 -27
  90. package/dist/server/index.d.ts +2 -0
  91. package/dist/server/index.js +32 -32
  92. package/dist/server/operations/create-schedule.d.ts +2 -0
  93. package/dist/server/operations/create-schedule.js +13 -2
  94. package/dist/server/rest-binding.d.ts +1 -1
  95. package/dist/server/runtime/task-dispatch.js +6 -0
  96. package/dist/server/runtime/task-polling.js +9 -1
  97. package/dist/server/runtime/task-reconciliation.js +2 -1
  98. package/dist/server/runtime/websocket-worker.js +7 -2
  99. package/dist/server/serve-internals.d.ts +28 -0
  100. package/dist/server/serve-internals.js +4 -2
  101. package/dist/server/task-queue-types.d.ts +2 -0
  102. package/dist/server/task-state.d.ts +4 -0
  103. package/dist/service-worker/index.d.ts +15 -14
  104. package/dist/service-worker/index.js +28 -28
  105. package/dist/service-worker/scheduler.d.ts +41 -1
  106. package/dist/service-worker/setup.d.ts +18 -1
  107. package/dist/service-worker/setup.js +7 -4
  108. package/dist/storage/auto.d.ts +36 -18
  109. package/dist/storage/auto.js +1 -1
  110. package/dist/storage/compressed-storage.js +1 -1
  111. package/dist/storage/indexeddb.d.ts +6 -1
  112. package/dist/storage/indexeddb.js +1 -1
  113. package/dist/storage/interface.js +1 -1
  114. package/dist/storage/lmdb.js +1 -1
  115. package/dist/storage/memory.js +1 -1
  116. package/dist/storage/neon.js +1 -1
  117. package/dist/storage/resolve.js +1 -1
  118. package/dist/storage/scoped-storage.js +1 -1
  119. package/dist/storage/testing.js +1 -1
  120. package/dist/storage/turso.js +1 -1
  121. package/dist/storage/typed-storage.d.ts +1 -1
  122. package/dist/storage/typed-storage.js +1 -1
  123. package/dist/storage/web-extension.d.ts +1 -1
  124. package/dist/storage/web-extension.js +1 -1
  125. package/dist/testing/index.js +32 -32
  126. package/dist/version.d.ts +1 -1
  127. package/dist/version.js +1 -1
  128. package/dist/worker/execute-with-interceptors.d.ts +9 -3
  129. package/dist/worker/execute-with-interceptors.js +14 -2
  130. package/dist/worker/long-poll.d.ts +2 -1
  131. package/dist/worker/long-poll.js +1 -1
  132. package/dist/worker/protocol-messages.d.ts +2 -0
  133. package/dist/worker/protocol-schemas.d.ts +8 -0
  134. package/dist/worker/protocol-schemas.js +1 -0
  135. package/dist/worker/protocol.js +1 -1
  136. package/dist/worker/remote-activity-context.d.ts +2 -0
  137. package/dist/workers/activity-runner.d.ts +2 -0
  138. package/dist/workers/activity-runner.js +9 -1
  139. package/dist/workers/workflow-runner.d.ts +2 -1
  140. package/dist/workers/workflow-runner.js +1 -0
  141. package/package.json +1 -1
@@ -0,0 +1,282 @@
1
+ import { hashString } from "../../runtime/portable.js";
2
+ import {
3
+ DurableActivityScopeError,
4
+ DurableActivityUnsupportedError,
5
+ runWithDurableActivityScope
6
+ } from "../context/durable-activity.js";
7
+ import {
8
+ readOrInitActivityRetrySleepFireAt,
9
+ runActivityWithRetryAtStep
10
+ } from "../context/run-operation.js";
11
+ import { AsyncActivityDeferral } from "./async-activity-completion.js";
12
+ import {
13
+ executeActivityOperationResult
14
+ } from "./operations-activity.js";
15
+ import { registerSleepResolver } from "./operations-time.js";
16
+ import { callMemoFunction } from "./state-utilities.js";
17
+ export async function callMemoFunctionWithDurableActivityScope(internals, workflowId, operation, callbacks) {
18
+ const context = internals.inlineStrategy?.getContext(workflowId);
19
+ if (context === void 0 || typeof operation.step !== "number" || !Number.isSafeInteger(operation.step) || operation.step < 0 || callbacks.getActivityOperationCallbacks === void 0)
20
+ return callMemoFunction(operation.fn);
21
+ const memoOperation = { ...operation, step: operation.step };
22
+ return new MemoDurableActivityScope(internals, workflowId, memoOperation, context, callbacks.getActivityOperationCallbacks(), callbacks.persistCheckpoint).run(() => callMemoFunction(operation.fn));
23
+ }
24
+
25
+ class MemoDurableActivityScope {
26
+ #internals;
27
+ #workflowId;
28
+ #operation;
29
+ #context;
30
+ #activityCallbacks;
31
+ #persistCheckpoint;
32
+ #scopeAbortController = new AbortController;
33
+ #pendingPromises = new Set;
34
+ #identityPrefix;
35
+ #activePromise;
36
+ #activeNonCancellableWriteCount = 0;
37
+ #closed = !1;
38
+ #closeReason;
39
+ #nextOrdinal = 0;
40
+ constructor(internals, workflowId, operation, context, activityCallbacks, persistCheckpoint) {
41
+ this.#internals = internals;
42
+ this.#workflowId = workflowId;
43
+ this.#operation = operation;
44
+ this.#context = context;
45
+ this.#activityCallbacks = activityCallbacks;
46
+ this.#persistCheckpoint = persistCheckpoint;
47
+ this.#identityPrefix = `memo:${operation.step}:${hashString(operation.key)}`;
48
+ this.#internals.workflowTypeByWorkflowId.set(workflowId, context.workflowType);
49
+ }
50
+ async run(execute) {
51
+ const cleanupAbortForwarding = this.#forwardAbortSignals();
52
+ try {
53
+ const result = await runWithDurableActivityScope(this, execute);
54
+ if (this.#pendingPromises.size > 0) {
55
+ const error = new DurableActivityScopeError("durableActivity() calls started inside ctx.memo() must be awaited before the memo callback returns.");
56
+ await this.#closeAndDrain(error);
57
+ throw error;
58
+ }
59
+ this.#close();
60
+ return result;
61
+ } catch (error) {
62
+ await this.#closeAndDrain(error);
63
+ throw error;
64
+ } finally {
65
+ cleanupAbortForwarding();
66
+ }
67
+ }
68
+ dispatch(invocation) {
69
+ try {
70
+ this.#throwIfClosed();
71
+ } catch (error) {
72
+ return Promise.reject(error);
73
+ }
74
+ if (this.#activePromise !== void 0)
75
+ return Promise.reject(new DurableActivityScopeError("durableActivity() calls inside one ctx.memo() scope must be awaited sequentially. Start the next durableActivity() call after the previous promise settles."));
76
+ const ordinal = this.#nextOrdinal;
77
+ this.#nextOrdinal += 1;
78
+ const execution = this.#executeInvocation(invocation, ordinal);
79
+ this.#activePromise = execution;
80
+ this.#pendingPromises.add(execution);
81
+ execution.finally(() => {
82
+ if (this.#activePromise === execution)
83
+ this.#activePromise = void 0;
84
+ this.#pendingPromises.delete(execution);
85
+ }).catch(() => {});
86
+ execution.catch(() => {});
87
+ return execution;
88
+ }
89
+ async#executeInvocation(invocation, ordinal) {
90
+ const activityStateKey = this.#activityStateKey(ordinal), generator = runActivityWithRetryAtStep(this.#context, invocation.activity, invocation.arguments, this.#operation.step, {
91
+ activityStateKey,
92
+ cacheResultStep: !1,
93
+ retryStateKey: activityStateKey,
94
+ retrySleep: (duration, nextAttempt) => this.#retrySleepOperation(duration, ordinal, nextAttempt)
95
+ });
96
+ let next = generator.next();
97
+ while (!next.done)
98
+ try {
99
+ const result = await this.#executeYieldedOperation(next.value, invocation, ordinal);
100
+ next = generator.next(result);
101
+ } catch (error) {
102
+ if (error instanceof AsyncActivityDeferral)
103
+ throw new DurableActivityUnsupportedError("ActivityContext.completeAsync() is not supported from durableActivity(). Use yield* ctx.run() for async-completion activities.");
104
+ next = generator.throw(error);
105
+ }
106
+ return next.value;
107
+ }
108
+ async#executeYieldedOperation(operation, invocation, ordinal) {
109
+ this.#throwIfClosed();
110
+ if (operation.type === "activity")
111
+ return this.#executeActivityOperation(operation, invocation.callerStack, ordinal);
112
+ if (operation.type === "sleep") {
113
+ await this.#raceWithScopeAbort(this.#executeDurableRetrySleepOperation(operation));
114
+ this.#throwIfClosed();
115
+ return;
116
+ }
117
+ throw new DurableActivityScopeError(`durableActivity() retry driver yielded unsupported operation "${operation.type}".`);
118
+ }
119
+ #executeActivityOperation(request, callerStack, ordinal) {
120
+ const attempt = typeof request.attempt === "number" ? request.attempt : 1, operation = {
121
+ ...request,
122
+ operationId: this.#activityOperationId(ordinal, attempt),
123
+ callerStack
124
+ };
125
+ return this.#raceWithScopeAbort(executeActivityOperationResult(this.#internals, this.#workflowId, operation, this.#activityCallbacks, this.#scopeAbortController.signal, void 0, {
126
+ reconciliationCompletion: "immediate-fenced",
127
+ beforeImmediateReconciliationCommit: () => this.#beginNonCancellableWrite()
128
+ }));
129
+ }
130
+ async#executeDurableRetrySleepOperation(operation) {
131
+ const finishCheckpointWrite = this.#beginNonCancellableWrite();
132
+ try {
133
+ await this.#persistCheckpoint(this.#workflowId, operation);
134
+ } finally {
135
+ finishCheckpointWrite();
136
+ }
137
+ this.#throwIfClosed();
138
+ if (operation.scheduledFireAt <= this.#internals.options.getNow())
139
+ return;
140
+ const { promise, resolve } = Promise.withResolvers(), finishTimerWrite = this.#beginNonCancellableWrite();
141
+ try {
142
+ await this.#internals.scheduler.schedule({
143
+ id: `sleep:${operation.operationId}`,
144
+ workflowId: this.#workflowId,
145
+ fireAt: operation.scheduledFireAt,
146
+ kind: "sleep"
147
+ });
148
+ } finally {
149
+ finishTimerWrite();
150
+ }
151
+ this.#throwIfClosed();
152
+ registerSleepResolver(this.#internals, this.#workflowId, operation.operationId, resolve, operation.scheduledFireAt);
153
+ await promise;
154
+ }
155
+ #activityOperationId(ordinal, attempt) {
156
+ return `${this.#activityStateKey(ordinal)}:activity:${attempt}`;
157
+ }
158
+ #retrySleepOperationId(ordinal, nextAttempt) {
159
+ return `${this.#activityStateKey(ordinal)}:retry-sleep:${nextAttempt}`;
160
+ }
161
+ *#retrySleepOperation(duration, ordinal, nextAttempt) {
162
+ const operationId = this.#retrySleepOperationId(ordinal, nextAttempt);
163
+ yield {
164
+ type: "sleep",
165
+ operationId,
166
+ duration,
167
+ scheduledFireAt: this.#readOrInitRetrySleepFireAt(operationId, duration)
168
+ };
169
+ }
170
+ #readOrInitRetrySleepFireAt(operationId, duration) {
171
+ return readOrInitActivityRetrySleepFireAt(this.#context, operationId, duration);
172
+ }
173
+ #activityStateKey(ordinal) {
174
+ if (!Number.isSafeInteger(ordinal) || ordinal < 0)
175
+ throw new DurableActivityScopeError(`Invalid durableActivity() call ordinal ${String(ordinal)} for ctx.memo() step ${String(this.#operation.step)}.`);
176
+ return `${this.#identityPrefix}:call:${String(ordinal)}`;
177
+ }
178
+ #raceWithScopeAbort(operation) {
179
+ operation.catch(() => {});
180
+ this.#throwIfClosed();
181
+ return new Promise((resolve, reject) => {
182
+ let settled = !1;
183
+ const signal = this.#scopeAbortController.signal, cleanup = () => {
184
+ signal.removeEventListener("abort", onAbort);
185
+ }, settle = (callback) => {
186
+ if (settled)
187
+ return;
188
+ settled = !0;
189
+ cleanup();
190
+ callback();
191
+ }, onAbort = () => {
192
+ if (this.#activeNonCancellableWriteCount > 0)
193
+ return;
194
+ settle(() => reject(this.#abortError()));
195
+ };
196
+ signal.addEventListener("abort", onAbort, { once: !0 });
197
+ if (signal.aborted) {
198
+ onAbort();
199
+ return;
200
+ }
201
+ operation.then((value) => {
202
+ settle(() => {
203
+ if (this.#closed || signal.aborted) {
204
+ reject(this.#abortError());
205
+ return;
206
+ }
207
+ resolve(value);
208
+ });
209
+ }).catch((error) => {
210
+ settle(() => reject(error));
211
+ });
212
+ });
213
+ }
214
+ #beginNonCancellableWrite() {
215
+ this.#throwIfClosed();
216
+ this.#activeNonCancellableWriteCount += 1;
217
+ let finished = !1;
218
+ return () => {
219
+ if (finished)
220
+ return;
221
+ finished = !0;
222
+ this.#activeNonCancellableWriteCount -= 1;
223
+ if (this.#closed && this.#activeNonCancellableWriteCount === 0 && !this.#scopeAbortController.signal.aborted)
224
+ this.#scopeAbortController.abort(this.#abortError());
225
+ };
226
+ }
227
+ #forwardAbortSignals() {
228
+ const signals = [this.#context.signal, this.#internals.abortController.signal], listeningSignals = [], onAbort = () => {
229
+ this.#close(new DurableActivityScopeError("durableActivity() scope closed before completion."));
230
+ }, cleanup = () => {
231
+ for (const signal of listeningSignals)
232
+ signal.removeEventListener("abort", onAbort);
233
+ };
234
+ for (const signal of signals) {
235
+ if (signal.aborted) {
236
+ onAbort();
237
+ return cleanup;
238
+ }
239
+ signal.addEventListener("abort", onAbort, { once: !0 });
240
+ listeningSignals.push(signal);
241
+ }
242
+ return cleanup;
243
+ }
244
+ #close(reason) {
245
+ if (this.#closed)
246
+ return;
247
+ this.#closed = !0;
248
+ this.#closeReason = toScopeError(reason);
249
+ if (this.#activeNonCancellableWriteCount === 0 && !this.#scopeAbortController.signal.aborted)
250
+ this.#scopeAbortController.abort(this.#closeReason);
251
+ }
252
+ async#closeAndDrain(reason) {
253
+ this.#close(reason);
254
+ if (this.#pendingPromises.size === 0)
255
+ return;
256
+ await Promise.allSettled(this.#pendingPromises);
257
+ }
258
+ #throwIfClosed() {
259
+ if (this.#closed || this.#scopeAbortController.signal.aborted)
260
+ throw this.#abortError();
261
+ }
262
+ #abortError() {
263
+ if (this.#closeReason !== void 0)
264
+ return this.#closeReason;
265
+ const reason = this.#scopeAbortController.signal.reason;
266
+ return reason instanceof Error ? reason : new DurableActivityScopeError("durableActivity() scope closed before completion.");
267
+ }
268
+ }
269
+ function toScopeError(reason) {
270
+ if (reason instanceof Error)
271
+ return reason;
272
+ if (reason === void 0)
273
+ return new DurableActivityScopeError("durableActivity() scope closed before completion.");
274
+ return new DurableActivityScopeError(formatCloseReason(reason));
275
+ }
276
+ function formatCloseReason(reason) {
277
+ if (typeof reason === "string")
278
+ return reason;
279
+ if (typeof reason === "number" || typeof reason === "boolean" || typeof reason === "bigint")
280
+ return reason.toString();
281
+ return "durableActivity() scope closed before completion.";
282
+ }
@@ -12,6 +12,10 @@ export type ActivityFunctionWithMetadata = ((...arguments_: unknown[]) => unknow
12
12
  type ActivityOperation = Extract<ContextOperationRequest, {
13
13
  type: 'activity';
14
14
  }>;
15
+ export interface ActivityExecutionOptions {
16
+ reconciliationCompletion?: 'stage-with-workflow-commit' | 'immediate-fenced';
17
+ beforeImmediateReconciliationCommit?: () => void | (() => void);
18
+ }
15
19
  export type ActivityOperationCallbacks = {
16
20
  runOperationWithResult: (workflowId: string, operation: ActivityOperation, execute: () => Promise<unknown>) => Promise<void>;
17
21
  finalizePendingTimelineEntry: (workflowId: string, status: 'completed' | 'failed', value: unknown) => void;
@@ -21,13 +25,13 @@ export type ActivityOperationCallbacks = {
21
25
  };
22
26
  export declare function buildActivityVerification(_internals: EngineInternals, activityName: string, verify: ActivityFunctionWithMetadata['verify'], context: ReturnType<typeof buildActivityVerificationContext>, result: unknown): Promise<void>;
23
27
  export declare function buildActivityCompensation(internals: EngineInternals, workflowId: string, operation: ActivityOperation, result: unknown): (() => Promise<void>) | undefined;
24
- export declare function invokeWorkerActivity(internals: EngineInternals, operationId: string, activityName: string, input: unknown, attempt: number): Promise<unknown>;
28
+ export declare function invokeWorkerActivity(internals: EngineInternals, operationId: string, activityName: string, input: unknown, attempt: number, workflowExecutionToken: string | undefined, activityAttemptToken: string | undefined): Promise<unknown>;
25
29
  export declare function invokeInlineActivity(internals: EngineInternals, workflowId: string, operation: ActivityOperation, activityContext: ActivityContext, _activityName: string, input: unknown): unknown;
26
30
  /**
27
31
  * Execute an activity function, dispatching to a Web Worker pool when
28
32
  * `activityExecution` is configured, or running inline on the main thread.
29
33
  */
30
34
  export declare function executeActivity(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks, attempt?: number, coordinatorSignal?: AbortSignal): Promise<unknown>;
31
- export declare function executeActivityOperationResult(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks, coordinatorSignal?: AbortSignal, speculativeState?: SpeculativeExecutionState): Promise<unknown>;
35
+ export declare function executeActivityOperationResult(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks, coordinatorSignal?: AbortSignal, speculativeState?: SpeculativeExecutionState, executionOptions?: ActivityExecutionOptions): Promise<unknown>;
32
36
  export declare function processActivityOperation(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks): Promise<void>;
33
37
  export {};
@@ -8,6 +8,7 @@ import { resolvePerAttemptTimeout, withPerAttemptTimeout } from "./activity-per-
8
8
  import {
9
9
  buildActivityReconciliationReference,
10
10
  buildActivityVerificationContext,
11
+ commitActivityReconciliationTransitionWithFencedWrite,
11
12
  createCompletedActivityReconciliationRecord,
12
13
  resolveActivityIdempotencyKey,
13
14
  resolveStartedActivityReconciliationRecord,
@@ -39,7 +40,7 @@ export function buildActivityCompensation(internals, workflowId, operation, resu
39
40
  await activity.compensate?.(operation.input, result);
40
41
  };
41
42
  }
42
- export async function invokeWorkerActivity(internals, operationId, activityName, input, attempt) {
43
+ export async function invokeWorkerActivity(internals, operationId, activityName, input, attempt, workflowExecutionToken, activityAttemptToken) {
43
44
  const dispatcher = internals.activityWorkerDispatcher;
44
45
  if (!dispatcher)
45
46
  throw Error(`No activity worker dispatcher available for "${activityName}"`);
@@ -47,7 +48,9 @@ export async function invokeWorkerActivity(internals, operationId, activityName,
47
48
  operationId,
48
49
  activityName,
49
50
  input,
50
- attempt
51
+ attempt,
52
+ ...workflowExecutionToken !== void 0 && { workflowExecutionToken },
53
+ ...activityAttemptToken !== void 0 && { activityAttemptToken }
51
54
  });
52
55
  if (result.status === "failed") {
53
56
  const error = Error(result.error);
@@ -69,12 +72,15 @@ function getActivityAttempt(operation) {
69
72
  const attempt = operation.attempt;
70
73
  return typeof attempt === "number" && Number.isInteger(attempt) && attempt > 0 ? attempt : 1;
71
74
  }
75
+ function getActivityStateKey(operation) {
76
+ return operation.activityStateKey ?? operation.step ?? 0;
77
+ }
72
78
  export async function executeActivity(internals, workflowId, operation, callbacks, attempt = getActivityAttempt(operation), coordinatorSignal) {
73
- const activityInput = operation.input, step = operation.step ?? 0;
74
- warnIfRetryMissingHeartbeat(internals, workflowId, step, attempt);
75
- const asyncToken = deriveAsyncActivityToken(workflowId, step, attempt), { perAttemptTimeoutMs, attemptAbortController, activitySignal } = resolvePerAttemptTimeout(internals, workflowId, operation, coordinatorSignal), activityContext = buildActivityContext(internals, workflowId, step, activitySignal, () => {
79
+ const activityInput = operation.input, activityStateKey = getActivityStateKey(operation), workflowExecutionToken = operation.workflowExecutionToken;
80
+ warnIfRetryMissingHeartbeat(internals, workflowId, activityStateKey, attempt);
81
+ const asyncToken = deriveAsyncActivityToken(workflowId, activityStateKey, attempt), { perAttemptTimeoutMs, attemptAbortController, activitySignal } = resolvePerAttemptTimeout(internals, workflowId, operation, coordinatorSignal), activityContext = buildActivityContext(internals, workflowId, workflowExecutionToken, activityStateKey, attempt, activitySignal, () => {
76
82
  throw new AsyncActivityDeferral(asyncToken);
77
- }), invokeActivity = internals.activityWorkerDispatcher ? (activityName, input) => invokeWorkerActivity(internals, operation.operationId, activityName, input, attempt) : (activityName, input) => withPerAttemptTimeout(invokeInlineActivity(internals, workflowId, operation, activityContext, activityName, input), perAttemptTimeoutMs, activityName, attempt, attemptAbortController), composedActivity = callbacks.getComposedActivityInterceptor(), executeWithActivityInterceptors = async (activityName, input, headers) => {
83
+ }), activityAttemptToken = activityContext.activityAttemptToken, invokeActivity = internals.activityWorkerDispatcher ? (activityName, input) => invokeWorkerActivity(internals, operation.operationId, activityName, input, attempt, workflowExecutionToken, activityAttemptToken) : (activityName, input) => withPerAttemptTimeout(invokeInlineActivity(internals, workflowId, operation, activityContext, activityName, input), perAttemptTimeoutMs, activityName, attempt, attemptAbortController), composedActivity = callbacks.getComposedActivityInterceptor(), executeWithActivityInterceptors = async (activityName, input, headers) => {
78
84
  if (!composedActivity)
79
85
  return invokeActivity(activityName, input);
80
86
  const activityInterception = {
@@ -107,7 +113,7 @@ export async function executeActivity(internals, workflowId, operation, callback
107
113
  copyActivityHeadersToOperation(operation, headers);
108
114
  return result;
109
115
  }
110
- export async function executeActivityOperationResult(internals, workflowId, operation, callbacks, coordinatorSignal, speculativeState) {
116
+ export async function executeActivityOperationResult(internals, workflowId, operation, callbacks, coordinatorSignal, speculativeState, executionOptions = {}) {
111
117
  const activity = getActivityFunctionWithMetadata(internals, workflowId, operation), idempotencyKey = resolveActivityIdempotencyKey(activity, operation), operationAttempt = getActivityAttempt(operation);
112
118
  if (idempotencyKey !== void 0) {
113
119
  const reference = await buildActivityReconciliationReference(workflowId, operation.activityName, idempotencyKey), started = await resolveStartedActivityReconciliationRecord(internals, workflowId, operation, reference, activity, idempotencyKey, operationAttempt);
@@ -119,16 +125,24 @@ export async function executeActivityOperationResult(internals, workflowId, oper
119
125
  validateActivityResultForReconciliation(result, internals.options.payloadSizePolicy.maxBytes);
120
126
  await finalizeActivityResult(internals, workflowId, operation, result, activity, idempotencyKey, started.attempt, speculativeState, !0);
121
127
  const completedRecord = createCompletedActivityReconciliationRecord(started, result, internals.options.getNow());
122
- stageActivityReconciliationTransitionWithAtomicWorkflowCommit(internals, workflowId, reference, started, completedRecord);
128
+ if (executionOptions.reconciliationCompletion === "immediate-fenced") {
129
+ const finishImmediateReconciliationCommit = executionOptions.beforeImmediateReconciliationCommit?.();
130
+ try {
131
+ await commitActivityReconciliationTransitionWithFencedWrite(internals, reference, started, completedRecord);
132
+ } finally {
133
+ finishImmediateReconciliationCommit?.();
134
+ }
135
+ } else
136
+ stageActivityReconciliationTransitionWithAtomicWorkflowCommit(internals, workflowId, reference, started, completedRecord);
123
137
  if (!speculativeState)
124
- clearLastHeartbeatForStep(internals, workflowId, operation.step ?? 0);
138
+ clearLastHeartbeatForStep(internals, workflowId, getActivityStateKey(operation));
125
139
  return result;
126
140
  }
127
141
  const result = await executeActivity(internals, workflowId, operation, callbacks, operationAttempt, coordinatorSignal);
128
142
  assertPayloadWithinLimit(result, internals.options.payloadSizePolicy.maxBytes, "activity result");
129
143
  await finalizeActivityResult(internals, workflowId, operation, result, activity, idempotencyKey, operationAttempt, speculativeState);
130
144
  if (!speculativeState)
131
- clearLastHeartbeatForStep(internals, workflowId, operation.step ?? 0);
145
+ clearLastHeartbeatForStep(internals, workflowId, getActivityStateKey(operation));
132
146
  return result;
133
147
  }
134
148
  async function finalizeActivityResult(internals, workflowId, operation, result, activity, idempotencyKey, attempt, speculativeState, awaitSpeculativeVerification = !1) {
@@ -1,5 +1,6 @@
1
1
  import type { ContextOperationRequest } from '../context.ts';
2
2
  import type { EngineInternals } from './internals.ts';
3
+ import type { ActivityOperationCallbacks } from './operations-activity.ts';
3
4
  import type { OperationWithCallerStack } from './operations-router.ts';
4
5
  type MemoOperation = Extract<ContextOperationRequest, {
5
6
  type: 'memo';
@@ -15,8 +16,10 @@ type ArchiveOperation = Extract<ContextOperationRequest, {
15
16
  }>;
16
17
  export type DataOperationCallbacks = {
17
18
  runOperationWithResult: (workflowId: string, operation: OperationWithCallerStack, execute: () => Promise<unknown>) => Promise<void>;
19
+ persistCheckpoint: (workflowId: string, operation: ContextOperationRequest) => Promise<void>;
20
+ getActivityOperationCallbacks?: () => ActivityOperationCallbacks;
18
21
  };
19
- export declare function processMemoOperation(_internals: EngineInternals, workflowId: string, operation: MemoOperation, callbacks: DataOperationCallbacks): Promise<void>;
22
+ export declare function processMemoOperation(internals: EngineInternals, workflowId: string, operation: MemoOperation, callbacks: DataOperationCallbacks): Promise<void>;
20
23
  export declare function processOffloadOperation(internals: EngineInternals, workflowId: string, operation: OffloadOperation, callbacks: DataOperationCallbacks): Promise<void>;
21
24
  export declare function processLoadOperation(internals: EngineInternals, workflowId: string, operation: LoadOperation, callbacks: DataOperationCallbacks): Promise<void>;
22
25
  /**
@@ -1,8 +1,8 @@
1
1
  import { KEYS } from "../../storage/interface.js";
2
2
  import { decode, encode } from "../codec.js";
3
- import { callMemoFunction } from "./state-utilities.js";
4
- export async function processMemoOperation(_internals, workflowId, operation, callbacks) {
5
- return callbacks.runOperationWithResult(workflowId, operation, async () => callMemoFunction(operation.fn));
3
+ import { callMemoFunctionWithDurableActivityScope } from "./memo-durable-activity.js";
4
+ export async function processMemoOperation(internals, workflowId, operation, callbacks) {
5
+ return callbacks.runOperationWithResult(workflowId, operation, async () => callMemoFunctionWithDurableActivityScope(internals, workflowId, operation, callbacks));
6
6
  }
7
7
  export async function processOffloadOperation(internals, workflowId, operation, callbacks) {
8
8
  return callbacks.runOperationWithResult(workflowId, operation, async () => {
@@ -12,7 +12,7 @@ export type TimeOperationCallbacks = {
12
12
  loadWorkflowState: (workflowId: string) => Promise<WorkflowState | null>;
13
13
  failWorkflow: (workflowId: string, error: Error) => Promise<void>;
14
14
  runSerializedWorkflowStateWrite: <Result>(workflowId: string, writeOperation: () => Promise<Result>) => Promise<Result>;
15
- beginWorkflowExecution: (workflowId: string, workflowType: string, input: unknown, checkpoint: Checkpoint, executionDeadline: number | undefined, executionStateOwnerId: string, registration: RegistrationEntry) => void;
15
+ beginWorkflowExecution: (workflowId: string, workflowExecutionToken: string | undefined, workflowType: string, input: unknown, checkpoint: Checkpoint, executionDeadline: number | undefined, executionStateOwnerId: string, registration: RegistrationEntry) => void;
16
16
  workflowVersionTupleFromState: (state: WorkflowState) => WorkflowVersionTuple;
17
17
  setWorkflowStartHeaders: (workflowId: string, headers: Map<string, string> | undefined) => void;
18
18
  loadWorkflowStartHeaders: (workflowId: string) => Promise<Map<string, string> | undefined>;
@@ -25,7 +25,7 @@ export type TimeOperationCallbacks = {
25
25
  };
26
26
  export declare function createDelayedStartTimerEntry(_internals: EngineInternals, workflowId: string, scheduledStartAt: number, options: StartOptions | undefined, callbacks: Pick<TimeOperationCallbacks, 'parseStartOptionDuration'>): TimerEntry;
27
27
  export declare function processSleepOperation(internals: EngineInternals, workflowId: string, operation: SleepOperation, callbacks: Pick<TimeOperationCallbacks, 'completeOperation' | 'loadWorkflowState'>): Promise<void>;
28
- export declare function registerSleepResolver(internals: EngineInternals, workflowId: string, operationId: string, resolve: () => void): void;
28
+ export declare function registerSleepResolver(internals: EngineInternals, workflowId: string, operationId: string, resolve: () => void, scheduledFireAt: number): void;
29
29
  export declare function startDelayedWorkflow(internals: EngineInternals, entry: TimerEntry, callbacks: Pick<TimeOperationCallbacks, 'beginWorkflowExecution' | 'dispatchEvent' | 'failWorkflow' | 'handleCleanupError' | 'loadWorkflowStartHeaders' | 'loadWorkflowState' | 'runSerializedWorkflowStateWrite' | 'setWorkflowStartHeaders' | 'workflowVersionTupleFromState'>): Promise<void>;
30
30
  export declare function handleTimerFired(internals: EngineInternals, entry: TimerEntry, callbacks: Pick<TimeOperationCallbacks, 'failWorkflow' | 'handleCleanupError' | 'loadWorkflowStartHeaders' | 'loadWorkflowState' | 'runDeferredTerminalCleanup' | 'runWorkflowFinalizer' | 'runSerializedWorkflowStateWrite' | 'handleScheduleTimer' | 'setWorkflowStartHeaders' | 'timeout' | 'beginWorkflowExecution' | 'dispatchEvent' | 'workflowVersionTupleFromState'>): Promise<void>;
31
31
  export {};
@@ -16,6 +16,18 @@ export function createDelayedStartTimerEntry(_internals, workflowId, scheduledSt
16
16
  }
17
17
  };
18
18
  }
19
+ function sleepTimerFiredEarly(internals, workflowId, operation) {
20
+ const workflowMarkers = internals.sleepTimersFiredWithoutResolver.get(workflowId);
21
+ if (!workflowMarkers)
22
+ return !1;
23
+ const markedFireAt = workflowMarkers.get(operation.operationId);
24
+ if (markedFireAt === void 0)
25
+ return !1;
26
+ workflowMarkers.delete(operation.operationId);
27
+ if (workflowMarkers.size === 0)
28
+ internals.sleepTimersFiredWithoutResolver.delete(workflowId);
29
+ return markedFireAt >= operation.scheduledFireAt;
30
+ }
19
31
  export async function processSleepOperation(internals, workflowId, operation, callbacks) {
20
32
  if (operation.scheduledFireAt <= internals.options.getNow()) {
21
33
  callbacks.completeOperation(workflowId, void 0);
@@ -28,13 +40,24 @@ export async function processSleepOperation(internals, workflowId, operation, ca
28
40
  fireAt: operation.scheduledFireAt,
29
41
  kind: "sleep"
30
42
  });
31
- registerSleepResolver(internals, workflowId, operation.operationId, resolve);
43
+ registerSleepResolver(internals, workflowId, operation.operationId, resolve, operation.scheduledFireAt);
44
+ const resolverKey = `${workflowId}:${operation.operationId}`;
45
+ if (sleepTimerFiredEarly(internals, workflowId, operation) && internals.sleepResolvers.has(resolverKey))
46
+ resolveSleepTimer(internals, {
47
+ id: `sleep:${operation.operationId}`,
48
+ workflowId,
49
+ fireAt: operation.scheduledFireAt,
50
+ kind: "sleep"
51
+ });
32
52
  await promise;
33
53
  if ((await callbacks.loadWorkflowState(workflowId))?.status === "running")
34
54
  callbacks.completeOperation(workflowId, void 0);
35
55
  }
36
- export function registerSleepResolver(internals, workflowId, operationId, resolve) {
37
- internals.sleepResolvers.set(`${workflowId}:${operationId}`, resolve);
56
+ export function registerSleepResolver(internals, workflowId, operationId, resolve, scheduledFireAt) {
57
+ internals.sleepResolvers.set(`${workflowId}:${operationId}`, {
58
+ resolve,
59
+ fireAt: scheduledFireAt
60
+ });
38
61
  let workflowOperations = internals.sleepResolversByWorkflow.get(workflowId);
39
62
  if (!workflowOperations) {
40
63
  workflowOperations = new Set;
@@ -94,7 +117,7 @@ export async function startDelayedWorkflow(internals, entry, callbacks) {
94
117
  internals.checkpoints.set(entry.workflowId, checkpoint);
95
118
  internals.workflowVersionTuples.set(entry.workflowId, callbacks.workflowVersionTupleFromState(runningState));
96
119
  callbacks.setWorkflowStartHeaders(entry.workflowId, await callbacks.loadWorkflowStartHeaders(entry.workflowId));
97
- callbacks.beginWorkflowExecution(entry.workflowId, runningState.type, runningState.input, checkpoint, executionDeadline, runningState.executionStateOwnerId ?? entry.workflowId, registration);
120
+ callbacks.beginWorkflowExecution(entry.workflowId, runningState.workflowExecutionToken, runningState.type, runningState.input, checkpoint, executionDeadline, runningState.executionStateOwnerId ?? entry.workflowId, registration);
98
121
  }
99
122
  async function loadDelayedWorkflowCheckpoint(internals, entry, callbacks) {
100
123
  const checkpointBytes = await internals.storage.get(KEYS.checkpoint(entry.workflowId));
@@ -168,11 +191,22 @@ async function handleReviewTimer(internals, entry, callbacks) {
168
191
  }
169
192
  function resolveSleepTimer(internals, entry) {
170
193
  const operationId = entry.id.replace("sleep:", ""), resolverKey = `${entry.workflowId}:${operationId}`, resolver = internals.sleepResolvers.get(resolverKey);
171
- if (!resolver)
194
+ if (!resolver) {
195
+ let workflowMarkers = internals.sleepTimersFiredWithoutResolver.get(entry.workflowId);
196
+ if (!workflowMarkers) {
197
+ workflowMarkers = new Map;
198
+ internals.sleepTimersFiredWithoutResolver.set(entry.workflowId, workflowMarkers);
199
+ }
200
+ const existing = workflowMarkers.get(operationId);
201
+ if (existing === void 0 || entry.fireAt > existing)
202
+ workflowMarkers.set(operationId, entry.fireAt);
203
+ return;
204
+ }
205
+ if (entry.fireAt < resolver.fireAt)
172
206
  return;
173
207
  internals.sleepResolvers.delete(resolverKey);
174
208
  untrackSleepResolver(internals, entry.workflowId, operationId);
175
- resolver();
209
+ resolver.resolve();
176
210
  }
177
211
  function untrackSleepResolver(internals, workflowId, operationId) {
178
212
  const workflowOperations = internals.sleepResolversByWorkflow.get(workflowId);
@@ -3,6 +3,7 @@ import { ReviewCompletedEvent, ReviewRequestedEvent } from "../review/events.js"
3
3
  import {
4
4
  ReviewTimeoutError
5
5
  } from "../review/index.js";
6
+ import { stageAtomicWorkflowCommitSideEffects } from "./checkpoint-side-effects.js";
6
7
  import {
7
8
  deleteCompletedReviewsForWorkflow,
8
9
  listCompletedReviewsFromStorage,
@@ -26,7 +27,7 @@ async function listPendingReviews(internals, filter) {
26
27
  return reviews;
27
28
  }
28
29
  async function dispatchCompletedReview(internals, reviewKey, reviewData, decisionResult, dispatchEvent) {
29
- await persistCompletedReviewRecord(internals.storage, reviewKey, reviewData, decisionResult);
30
+ await persistCompletedReviewRecord(internals, reviewKey, reviewData, decisionResult);
30
31
  dispatchEvent(new ReviewCompletedEvent(reviewData.workflowId, reviewData.reviewId, decisionResult.decision, decisionResult.reviewer, decisionResult.timestamp - reviewData.createdAt));
31
32
  }
32
33
  export async function listReviews(internals, filter = {}) {
@@ -96,9 +97,11 @@ export async function handleReviewEscalationTimer(internals, workflowId, reviewI
96
97
  if (entry.id === `review-timeout:${reviewId}`) {
97
98
  internals.reviewWaiters.delete(waiterKey);
98
99
  untrackWaiterKey(internals.reviewWaitersByWorkflow, workflowId, waiterKey);
99
- const elapsed = internals.options.getNow() - reviewRequest.createdAt;
100
- await internals.storage.delete(KEYS.review(workflowId, reviewId));
101
- const timeoutError = new ReviewTimeoutError(reviewId, elapsed);
100
+ const elapsed = internals.options.getNow() - reviewRequest.createdAt, timeoutError = new ReviewTimeoutError(reviewId, elapsed);
101
+ stageAtomicWorkflowCommitSideEffects(internals, workflowId, {
102
+ operations: [{ type: "delete", key: KEYS.review(workflowId, reviewId) }],
103
+ conditions: []
104
+ });
102
105
  await callbacks.failWorkflow(workflowId, timeoutError);
103
106
  resolve({ ok: !1, error: timeoutError });
104
107
  return !0;
@@ -12,6 +12,8 @@ class ScheduleStatePersistenceError extends Error {
12
12
  }
13
13
  }
14
14
  export async function handleScheduleTimer(internals, entry, callbacks) {
15
+ if (internals.deposed)
16
+ return;
15
17
  const state = await loadScheduleState(internals, entry.workflowId);
16
18
  if (!isCurrentActiveScheduleTimer(state, entry))
17
19
  return;
@@ -35,6 +35,9 @@ export async function schedule(internals, type, input, spec, options) {
35
35
  id: scheduleId,
36
36
  workflowType: type,
37
37
  input,
38
+ ...normalizedOptions.description !== void 0 && {
39
+ description: normalizedOptions.description
40
+ },
38
41
  ...cadenceFields,
39
42
  status: "active",
40
43
  overlap: normalizedOptions.overlap,
@@ -93,7 +93,7 @@ export async function writeScheduleState(internals, state, options) {
93
93
  kind: "schedule"
94
94
  }));
95
95
  }
96
- await internals.storage.batch(operations);
96
+ await commitFencedEngineWrite(internals, operations, [], () => Error(`Schedule state commit for schedule "${state.id}" lost its precondition.`));
97
97
  }
98
98
  export async function loadWorkflowStartHeaders(internals, workflowId) {
99
99
  const bytes = await internals.storage.get(KEYS.workflowHeaders(workflowId));
@@ -43,23 +43,25 @@ function cleanupTrackedWaiter(internals, workflowId, kind) {
43
43
  }
44
44
  function cleanupSleepResolvers(internals, workflowId) {
45
45
  const sleepOps = internals.sleepResolversByWorkflow.get(workflowId);
46
- if (!sleepOps)
47
- return;
48
- for (const operationId of sleepOps) {
49
- const key = `${workflowId}:${operationId}`, resolver = internals.sleepResolvers.get(key);
50
- if (resolver)
51
- resolver();
52
- internals.sleepResolvers.delete(key);
46
+ if (sleepOps) {
47
+ for (const operationId of sleepOps) {
48
+ const key = `${workflowId}:${operationId}`, resolver = internals.sleepResolvers.get(key);
49
+ if (resolver)
50
+ resolver.resolve();
51
+ internals.sleepResolvers.delete(key);
52
+ }
53
+ internals.sleepResolversByWorkflow.delete(workflowId);
53
54
  }
54
- internals.sleepResolversByWorkflow.delete(workflowId);
55
+ internals.sleepTimersFiredWithoutResolver.delete(workflowId);
55
56
  }
56
57
  function evictSleepResolversWithoutResolving(internals, workflowId) {
57
58
  const sleepOps = internals.sleepResolversByWorkflow.get(workflowId);
58
- if (!sleepOps)
59
- return;
60
- for (const operationId of sleepOps)
61
- internals.sleepResolvers.delete(`${workflowId}:${operationId}`);
62
- internals.sleepResolversByWorkflow.delete(workflowId);
59
+ if (sleepOps) {
60
+ for (const operationId of sleepOps)
61
+ internals.sleepResolvers.delete(`${workflowId}:${operationId}`);
62
+ internals.sleepResolversByWorkflow.delete(workflowId);
63
+ }
64
+ internals.sleepTimersFiredWithoutResolver.delete(workflowId);
63
65
  }
64
66
  function cleanupConditionWaiters(internals, workflowId) {
65
67
  const resolver = internals.conditionWaiters.get(workflowId);
@@ -50,4 +50,4 @@ export type FinalizerAttemptResult = {
50
50
  * @param attempt - 1-based attempt number, for the per-attempt timeout error message
51
51
  * @param shutdownSignal - the engine's dispose/shutdown abort signal; aborting it stops a cooperating finalizer
52
52
  */
53
- export declare function runFinalizerActivity(finalizer: RunnableFinalizer, input: unknown, attempt: number, shutdownSignal: AbortSignal): Promise<FinalizerAttemptResult>;
53
+ export declare function runFinalizerActivity(finalizer: RunnableFinalizer, input: unknown, attempt: number, shutdownSignal: AbortSignal, workflowExecutionToken?: string): Promise<FinalizerAttemptResult>;