@workflow/core 4.0.1-beta.4 → 4.0.1-beta.40

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 (147) hide show
  1. package/LICENSE.md +201 -21
  2. package/dist/builtins.js +1 -1
  3. package/dist/class-serialization.d.ts +26 -0
  4. package/dist/class-serialization.d.ts.map +1 -0
  5. package/dist/class-serialization.js +66 -0
  6. package/dist/create-hook.js +1 -1
  7. package/dist/define-hook.d.ts +40 -25
  8. package/dist/define-hook.d.ts.map +1 -1
  9. package/dist/define-hook.js +22 -27
  10. package/dist/events-consumer.js +1 -1
  11. package/dist/flushable-stream.d.ts +82 -0
  12. package/dist/flushable-stream.d.ts.map +1 -0
  13. package/dist/flushable-stream.js +214 -0
  14. package/dist/global.d.ts +12 -2
  15. package/dist/global.d.ts.map +1 -1
  16. package/dist/global.js +32 -8
  17. package/dist/index.d.ts +3 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -2
  20. package/dist/logger.js +1 -1
  21. package/dist/observability.d.ts +60 -0
  22. package/dist/observability.d.ts.map +1 -1
  23. package/dist/observability.js +175 -19
  24. package/dist/parse-name.d.ts +12 -0
  25. package/dist/parse-name.d.ts.map +1 -1
  26. package/dist/parse-name.js +28 -3
  27. package/dist/private.d.ts +10 -1
  28. package/dist/private.d.ts.map +1 -1
  29. package/dist/private.js +6 -1
  30. package/dist/runtime/helpers.d.ts +64 -0
  31. package/dist/runtime/helpers.d.ts.map +1 -0
  32. package/dist/runtime/helpers.js +243 -0
  33. package/dist/runtime/resume-hook.d.ts +16 -11
  34. package/dist/runtime/resume-hook.d.ts.map +1 -1
  35. package/dist/runtime/resume-hook.js +76 -64
  36. package/dist/runtime/start.d.ts +10 -0
  37. package/dist/runtime/start.d.ts.map +1 -1
  38. package/dist/runtime/start.js +56 -45
  39. package/dist/runtime/step-handler.d.ts +7 -0
  40. package/dist/runtime/step-handler.d.ts.map +1 -0
  41. package/dist/runtime/step-handler.js +353 -0
  42. package/dist/runtime/suspension-handler.d.ts +20 -0
  43. package/dist/runtime/suspension-handler.d.ts.map +1 -0
  44. package/dist/runtime/suspension-handler.js +179 -0
  45. package/dist/runtime/world.d.ts.map +1 -1
  46. package/dist/runtime/world.js +22 -21
  47. package/dist/runtime.d.ts +3 -7
  48. package/dist/runtime.d.ts.map +1 -1
  49. package/dist/runtime.js +76 -334
  50. package/dist/schemas.d.ts +1 -15
  51. package/dist/schemas.d.ts.map +1 -1
  52. package/dist/schemas.js +2 -15
  53. package/dist/serialization.d.ts +74 -10
  54. package/dist/serialization.d.ts.map +1 -1
  55. package/dist/serialization.js +295 -56
  56. package/dist/sleep.d.ts +33 -0
  57. package/dist/sleep.d.ts.map +1 -0
  58. package/dist/sleep.js +10 -0
  59. package/dist/source-map.d.ts +10 -0
  60. package/dist/source-map.d.ts.map +1 -0
  61. package/dist/source-map.js +56 -0
  62. package/dist/step/context-storage.d.ts +2 -0
  63. package/dist/step/context-storage.d.ts.map +1 -1
  64. package/dist/step/context-storage.js +1 -1
  65. package/dist/step/get-closure-vars.d.ts +9 -0
  66. package/dist/step/get-closure-vars.d.ts.map +1 -0
  67. package/dist/step/get-closure-vars.js +16 -0
  68. package/dist/step/get-step-metadata.js +1 -1
  69. package/dist/step/get-workflow-metadata.js +1 -1
  70. package/dist/step/writable-stream.d.ts +14 -0
  71. package/dist/step/writable-stream.d.ts.map +1 -0
  72. package/dist/step/writable-stream.js +30 -0
  73. package/dist/step.d.ts +1 -1
  74. package/dist/step.d.ts.map +1 -1
  75. package/dist/step.js +51 -11
  76. package/dist/symbols.d.ts +7 -0
  77. package/dist/symbols.d.ts.map +1 -1
  78. package/dist/symbols.js +8 -1
  79. package/dist/telemetry/semantic-conventions.d.ts +66 -38
  80. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  81. package/dist/telemetry/semantic-conventions.js +16 -3
  82. package/dist/telemetry.d.ts +8 -4
  83. package/dist/telemetry.d.ts.map +1 -1
  84. package/dist/telemetry.js +39 -6
  85. package/dist/types.d.ts +0 -7
  86. package/dist/types.d.ts.map +1 -1
  87. package/dist/types.js +1 -26
  88. package/dist/util.d.ts +9 -27
  89. package/dist/util.d.ts.map +1 -1
  90. package/dist/util.js +37 -44
  91. package/dist/vm/index.js +2 -2
  92. package/dist/vm/uuid.js +1 -1
  93. package/dist/workflow/create-hook.js +1 -1
  94. package/dist/workflow/define-hook.d.ts +3 -3
  95. package/dist/workflow/define-hook.d.ts.map +1 -1
  96. package/dist/workflow/define-hook.js +1 -1
  97. package/dist/workflow/get-workflow-metadata.js +1 -1
  98. package/dist/workflow/hook.d.ts.map +1 -1
  99. package/dist/workflow/hook.js +6 -9
  100. package/dist/workflow/index.d.ts +1 -0
  101. package/dist/workflow/index.d.ts.map +1 -1
  102. package/dist/workflow/index.js +2 -1
  103. package/dist/workflow/sleep.d.ts +4 -0
  104. package/dist/workflow/sleep.d.ts.map +1 -0
  105. package/dist/workflow/sleep.js +54 -0
  106. package/dist/workflow/writable-stream.js +1 -1
  107. package/dist/workflow.d.ts.map +1 -1
  108. package/dist/workflow.js +60 -9
  109. package/dist/writable-stream.d.ts +5 -4
  110. package/dist/writable-stream.d.ts.map +1 -1
  111. package/dist/writable-stream.js +7 -6
  112. package/package.json +23 -18
  113. package/dist/builtins.js.map +0 -1
  114. package/dist/create-hook.js.map +0 -1
  115. package/dist/define-hook.js.map +0 -1
  116. package/dist/events-consumer.js.map +0 -1
  117. package/dist/global.js.map +0 -1
  118. package/dist/index.js.map +0 -1
  119. package/dist/logger.js.map +0 -1
  120. package/dist/observability.js.map +0 -1
  121. package/dist/parse-name.js.map +0 -1
  122. package/dist/private.js.map +0 -1
  123. package/dist/runtime/resume-hook.js.map +0 -1
  124. package/dist/runtime/start.js.map +0 -1
  125. package/dist/runtime/world.js.map +0 -1
  126. package/dist/runtime.js.map +0 -1
  127. package/dist/schemas.js.map +0 -1
  128. package/dist/serialization.js.map +0 -1
  129. package/dist/step/context-storage.js.map +0 -1
  130. package/dist/step/get-step-metadata.js.map +0 -1
  131. package/dist/step/get-workflow-metadata.js.map +0 -1
  132. package/dist/step.js.map +0 -1
  133. package/dist/symbols.js.map +0 -1
  134. package/dist/telemetry/semantic-conventions.js.map +0 -1
  135. package/dist/telemetry.js.map +0 -1
  136. package/dist/types.js.map +0 -1
  137. package/dist/util.js.map +0 -1
  138. package/dist/vm/index.js.map +0 -1
  139. package/dist/vm/uuid.js.map +0 -1
  140. package/dist/workflow/create-hook.js.map +0 -1
  141. package/dist/workflow/define-hook.js.map +0 -1
  142. package/dist/workflow/get-workflow-metadata.js.map +0 -1
  143. package/dist/workflow/hook.js.map +0 -1
  144. package/dist/workflow/index.js.map +0 -1
  145. package/dist/workflow/writable-stream.js.map +0 -1
  146. package/dist/workflow.js.map +0 -1
  147. package/dist/writable-stream.js.map +0 -1
@@ -1,57 +1,68 @@
1
1
  import { waitUntil } from '@vercel/functions';
2
2
  import { WorkflowRuntimeError } from '@workflow/errors';
3
+ import { withResolvers } from '@workflow/utils';
3
4
  import { Run } from '../runtime.js';
4
5
  import { dehydrateWorkflowArguments } from '../serialization.js';
5
6
  import * as Attribute from '../telemetry/semantic-conventions.js';
6
7
  import { serializeTraceCarrier, trace } from '../telemetry.js';
8
+ import { waitedUntil } from '../util.js';
7
9
  import { getWorld } from './world.js';
8
10
  export async function start(workflow, argsOrOptions, options) {
9
- // @ts-expect-error this field is added by our client transform
10
- const workflowName = workflow.workflowId;
11
- if (!workflowName) {
12
- throw new WorkflowRuntimeError(`'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.`, { slug: 'start-invalid-workflow-function' });
13
- }
14
- return trace(`WORKFLOW.start ${workflowName}`, async (span) => {
15
- span?.setAttributes({
16
- ...Attribute.WorkflowName(workflowName),
17
- ...Attribute.WorkflowOperation('start'),
18
- });
19
- let args = [];
20
- let opts = options ?? {};
21
- if (Array.isArray(argsOrOptions)) {
22
- args = argsOrOptions;
23
- }
24
- else if (typeof argsOrOptions === 'object') {
25
- opts = argsOrOptions;
11
+ return await waitedUntil(() => {
12
+ // @ts-expect-error this field is added by our client transform
13
+ const workflowName = workflow?.workflowId;
14
+ if (!workflowName) {
15
+ throw new WorkflowRuntimeError(`'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.`, { slug: 'start-invalid-workflow-function' });
26
16
  }
27
- span?.setAttributes({
28
- ...Attribute.WorkflowArgumentsCount(args.length),
29
- });
30
- const world = getWorld();
31
- const deploymentId = opts.deploymentId ?? (await world.getDeploymentId());
32
- const ops = [];
33
- const workflowArguments = dehydrateWorkflowArguments(args, ops);
34
- // Serialize current trace context to propagate across queue boundary
35
- const traceCarrier = await serializeTraceCarrier();
36
- const runResponse = await world.runs.create({
37
- deploymentId: deploymentId,
38
- workflowName: workflowName,
39
- input: workflowArguments,
40
- executionContext: { traceCarrier },
41
- });
42
- waitUntil(Promise.all(ops));
43
- span?.setAttributes({
44
- ...Attribute.WorkflowRunId(runResponse.runId),
45
- ...Attribute.WorkflowRunStatus(runResponse.status),
46
- ...Attribute.DeploymentId(deploymentId),
47
- });
48
- await world.queue(`__wkf_workflow_${workflowName}`, {
49
- runId: runResponse.runId,
50
- traceCarrier,
51
- }, {
52
- deploymentId,
17
+ return trace(`WORKFLOW.start ${workflowName}`, async (span) => {
18
+ span?.setAttributes({
19
+ ...Attribute.WorkflowName(workflowName),
20
+ ...Attribute.WorkflowOperation('start'),
21
+ });
22
+ let args = [];
23
+ let opts = options ?? {};
24
+ if (Array.isArray(argsOrOptions)) {
25
+ args = argsOrOptions;
26
+ }
27
+ else if (typeof argsOrOptions === 'object') {
28
+ opts = argsOrOptions;
29
+ }
30
+ span?.setAttributes({
31
+ ...Attribute.WorkflowArgumentsCount(args.length),
32
+ });
33
+ const world = opts?.world ?? getWorld();
34
+ const deploymentId = opts.deploymentId ?? (await world.getDeploymentId());
35
+ const ops = [];
36
+ const { promise: runIdPromise, resolve: resolveRunId } = withResolvers();
37
+ const workflowArguments = dehydrateWorkflowArguments(args, ops, runIdPromise);
38
+ // Serialize current trace context to propagate across queue boundary
39
+ const traceCarrier = await serializeTraceCarrier();
40
+ const runResponse = await world.runs.create({
41
+ deploymentId: deploymentId,
42
+ workflowName: workflowName,
43
+ input: workflowArguments,
44
+ executionContext: { traceCarrier },
45
+ });
46
+ resolveRunId(runResponse.runId);
47
+ waitUntil(Promise.all(ops).catch((err) => {
48
+ // Ignore expected client disconnect errors (e.g., browser refresh during streaming)
49
+ const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
50
+ if (!isAbortError)
51
+ throw err;
52
+ }));
53
+ span?.setAttributes({
54
+ ...Attribute.WorkflowRunId(runResponse.runId),
55
+ ...Attribute.WorkflowRunStatus(runResponse.status),
56
+ ...Attribute.DeploymentId(deploymentId),
57
+ });
58
+ await world.queue(`__wkf_workflow_${workflowName}`, {
59
+ runId: runResponse.runId,
60
+ traceCarrier,
61
+ }, {
62
+ deploymentId,
63
+ });
64
+ return new Run(runResponse.runId);
53
65
  });
54
- return new Run(runResponse.runId);
55
66
  });
56
67
  }
57
- //# sourceMappingURL=start.js.map
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9zdGFydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRWhELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFcEMsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDakUsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN6QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBa0R0QyxNQUFNLENBQUMsS0FBSyxVQUFVLEtBQUssQ0FDekIsUUFBNkQsRUFDN0QsYUFBb0MsRUFDcEMsT0FBc0I7SUFFdEIsT0FBTyxNQUFNLFdBQVcsQ0FBQyxHQUFHLEVBQUU7UUFDNUIsK0RBQStEO1FBQy9ELE1BQU0sWUFBWSxHQUFHLFFBQVEsRUFBRSxVQUFVLENBQUM7UUFFMUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ2xCLE1BQU0sSUFBSSxvQkFBb0IsQ0FDNUIsa0tBQWtLLEVBQ2xLLEVBQUUsSUFBSSxFQUFFLGlDQUFpQyxFQUFFLENBQzVDLENBQUM7UUFDSixDQUFDO1FBRUQsT0FBTyxLQUFLLENBQUMsa0JBQWtCLFlBQVksRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUM1RCxJQUFJLEVBQUUsYUFBYSxDQUFDO2dCQUNsQixHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDO2dCQUN2QyxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUM7YUFDeEMsQ0FBQyxDQUFDO1lBRUgsSUFBSSxJQUFJLEdBQW1CLEVBQUUsQ0FBQztZQUM5QixJQUFJLElBQUksR0FBaUIsT0FBTyxJQUFJLEVBQUUsQ0FBQztZQUN2QyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztnQkFDakMsSUFBSSxHQUFHLGFBQStCLENBQUM7WUFDekMsQ0FBQztpQkFBTSxJQUFJLE9BQU8sYUFBYSxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUM3QyxJQUFJLEdBQUcsYUFBYSxDQUFDO1lBQ3ZCLENBQUM7WUFFRCxJQUFJLEVBQUUsYUFBYSxDQUFDO2dCQUNsQixHQUFHLFNBQVMsQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO2FBQ2pELENBQUMsQ0FBQztZQUVILE1BQU0sS0FBSyxHQUFHLElBQUksRUFBRSxLQUFLLElBQUksUUFBUSxFQUFFLENBQUM7WUFDeEMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFDLENBQUM7WUFDMUUsTUFBTSxHQUFHLEdBQW9CLEVBQUUsQ0FBQztZQUNoQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLEdBQ3BELGFBQWEsRUFBVSxDQUFDO1lBRTFCLE1BQU0saUJBQWlCLEdBQUcsMEJBQTBCLENBQ2xELElBQUksRUFDSixHQUFHLEVBQ0gsWUFBWSxDQUNiLENBQUM7WUFDRixxRUFBcUU7WUFDckUsTUFBTSxZQUFZLEdBQUcsTUFBTSxxQkFBcUIsRUFBRSxDQUFDO1lBRW5ELE1BQU0sV0FBVyxHQUFHLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7Z0JBQzFDLFlBQVksRUFBRSxZQUFZO2dCQUMxQixZQUFZLEVBQUUsWUFBWTtnQkFDMUIsS0FBSyxFQUFFLGlCQUFpQjtnQkFDeEIsZ0JBQWdCLEVBQUUsRUFBRSxZQUFZLEVBQUU7YUFDbkMsQ0FBQyxDQUFDO1lBRUgsWUFBWSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVoQyxTQUFTLENBQ1AsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtnQkFDN0Isb0ZBQW9GO2dCQUNwRixNQUFNLFlBQVksR0FDaEIsR0FBRyxFQUFFLElBQUksS0FBSyxZQUFZLElBQUksR0FBRyxFQUFFLElBQUksS0FBSyxpQkFBaUIsQ0FBQztnQkFDaEUsSUFBSSxDQUFDLFlBQVk7b0JBQUUsTUFBTSxHQUFHLENBQUM7WUFDL0IsQ0FBQyxDQUFDLENBQ0gsQ0FBQztZQUVGLElBQUksRUFBRSxhQUFhLENBQUM7Z0JBQ2xCLEdBQUcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDO2dCQUM3QyxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDO2dCQUNsRCxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDO2FBQ3hDLENBQUMsQ0FBQztZQUVILE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FDZixrQkFBa0IsWUFBWSxFQUFFLEVBQ2hDO2dCQUNFLEtBQUssRUFBRSxXQUFXLENBQUMsS0FBSztnQkFDeEIsWUFBWTthQUNtQixFQUNqQztnQkFDRSxZQUFZO2FBQ2IsQ0FDRixDQUFDO1lBRUYsT0FBTyxJQUFJLEdBQUcsQ0FBVSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0MsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMifQ==
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A single route that handles any step execution request and routes to the
3
+ * appropriate step function. We may eventually want to create different bundles
4
+ * for each step, this is temporary.
5
+ */
6
+ export declare const stepEntrypoint: (req: Request) => Promise<Response>;
7
+ //# sourceMappingURL=step-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-handler.d.ts","sourceRoot":"","sources":["../../src/runtime/step-handler.ts"],"names":[],"mappings":"AA8bA;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CACjB,CAAC"}
@@ -0,0 +1,353 @@
1
+ import { waitUntil } from '@vercel/functions';
2
+ import { FatalError, RetryableError, WorkflowAPIError, WorkflowRuntimeError, } from '@workflow/errors';
3
+ import { pluralize } from '@workflow/utils';
4
+ import { getPort } from '@workflow/utils/get-port';
5
+ import { StepInvokePayloadSchema } from '@workflow/world';
6
+ import { runtimeLogger } from '../logger.js';
7
+ import { getStepFunction } from '../private.js';
8
+ import { dehydrateStepReturnValue, hydrateStepArguments, } from '../serialization.js';
9
+ import { contextStorage } from '../step/context-storage.js';
10
+ import * as Attribute from '../telemetry/semantic-conventions.js';
11
+ import { getSpanKind, linkToCurrentContext, serializeTraceCarrier, trace, withTraceContext, } from '../telemetry.js';
12
+ import { getErrorName, getErrorStack } from '../types.js';
13
+ import { getQueueOverhead, handleHealthCheckMessage, parseHealthCheckPayload, queueMessage, withHealthCheck, } from './helpers.js';
14
+ import { getWorld, getWorldHandlers } from './world.js';
15
+ const DEFAULT_STEP_MAX_RETRIES = 3;
16
+ const stepHandler = getWorldHandlers().createQueueHandler('__wkf_step_', async (message_, metadata) => {
17
+ // Check if this is a health check message
18
+ // NOTE: Health check messages are intentionally unauthenticated for monitoring purposes.
19
+ // They only write a simple status response to a stream and do not expose sensitive data.
20
+ // The stream name includes a unique correlationId that must be known by the caller.
21
+ const healthCheck = parseHealthCheckPayload(message_);
22
+ if (healthCheck) {
23
+ await handleHealthCheckMessage(healthCheck, 'step');
24
+ return;
25
+ }
26
+ const { workflowName, workflowRunId, workflowStartedAt, stepId, traceCarrier: traceContext, requestedAt, } = StepInvokePayloadSchema.parse(message_);
27
+ const spanLinks = await linkToCurrentContext();
28
+ // Execute step within the propagated trace context
29
+ return await withTraceContext(traceContext, async () => {
30
+ // Extract the step name from the topic name
31
+ const stepName = metadata.queueName.slice('__wkf_step_'.length);
32
+ const world = getWorld();
33
+ // Get the port early to avoid async operations during step execution
34
+ const port = await getPort();
35
+ return trace(`STEP ${stepName}`, { kind: await getSpanKind('CONSUMER'), links: spanLinks }, async (span) => {
36
+ span?.setAttributes({
37
+ ...Attribute.StepName(stepName),
38
+ ...Attribute.StepAttempt(metadata.attempt),
39
+ ...Attribute.QueueName(metadata.queueName),
40
+ ...Attribute.QueueMessageId(metadata.messageId),
41
+ ...getQueueOverhead({ requestedAt }),
42
+ });
43
+ const stepFn = getStepFunction(stepName);
44
+ if (!stepFn) {
45
+ throw new Error(`Step "${stepName}" not found`);
46
+ }
47
+ if (typeof stepFn !== 'function') {
48
+ throw new Error(`Step "${stepName}" is not a function (got ${typeof stepFn})`);
49
+ }
50
+ const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
51
+ span?.setAttributes({
52
+ ...Attribute.WorkflowName(workflowName),
53
+ ...Attribute.WorkflowRunId(workflowRunId),
54
+ ...Attribute.StepId(stepId),
55
+ ...Attribute.StepMaxRetries(maxRetries),
56
+ ...Attribute.StepTracePropagated(!!traceContext),
57
+ });
58
+ let step = await world.steps.get(workflowRunId, stepId);
59
+ runtimeLogger.debug('Step execution details', {
60
+ stepName,
61
+ stepId: step.stepId,
62
+ status: step.status,
63
+ attempt: step.attempt,
64
+ });
65
+ span?.setAttributes({
66
+ ...Attribute.StepStatus(step.status),
67
+ });
68
+ // Check if the step has a `retryAfter` timestamp that hasn't been reached yet
69
+ const now = Date.now();
70
+ if (step.retryAfter && step.retryAfter.getTime() > now) {
71
+ const timeoutSeconds = Math.ceil((step.retryAfter.getTime() - now) / 1000);
72
+ span?.setAttributes({
73
+ ...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
74
+ });
75
+ runtimeLogger.debug('Step retryAfter timestamp not yet reached', {
76
+ stepName,
77
+ stepId: step.stepId,
78
+ retryAfter: step.retryAfter,
79
+ timeoutSeconds,
80
+ });
81
+ return { timeoutSeconds };
82
+ }
83
+ let result;
84
+ const attempt = step.attempt + 1;
85
+ // Check max retries FIRST before any state changes.
86
+ // This handles edge cases where the step handler is invoked after max retries have been exceeded
87
+ // (e.g., when the step repeatedly times out or fails before reaching the catch handler at line 822).
88
+ // Without this check, the step would retry forever.
89
+ // Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
90
+ // Use > here (not >=) because this guards against re-invocation AFTER all attempts are used.
91
+ // The post-failure check uses >= to decide whether to retry after a failure.
92
+ if (attempt > maxRetries + 1) {
93
+ const retryCount = attempt - 1;
94
+ const errorMessage = `Step "${stepName}" exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`;
95
+ console.error(`[Workflows] "${workflowRunId}" - ${errorMessage}`);
96
+ // Update step status first (idempotent), then create event
97
+ await world.steps.update(workflowRunId, stepId, {
98
+ status: 'failed',
99
+ error: {
100
+ message: errorMessage,
101
+ stack: undefined,
102
+ },
103
+ });
104
+ await world.events.create(workflowRunId, {
105
+ eventType: 'step_failed',
106
+ correlationId: stepId,
107
+ eventData: {
108
+ error: errorMessage,
109
+ stack: step.error?.stack,
110
+ fatal: true,
111
+ },
112
+ });
113
+ span?.setAttributes({
114
+ ...Attribute.StepStatus('failed'),
115
+ ...Attribute.StepRetryExhausted(true),
116
+ });
117
+ // Re-invoke the workflow to handle the failed step
118
+ await queueMessage(world, `__wkf_workflow_${workflowName}`, {
119
+ runId: workflowRunId,
120
+ traceCarrier: await serializeTraceCarrier(),
121
+ requestedAt: new Date(),
122
+ });
123
+ return;
124
+ }
125
+ try {
126
+ if (!['pending', 'running'].includes(step.status)) {
127
+ // We should only be running the step if it's either
128
+ // a) pending - initial state, or state set on re-try
129
+ // b) running - if a step fails mid-execution, like a function timeout
130
+ // otherwise, the step has been invoked erroneously
131
+ console.error(`[Workflows] "${workflowRunId}" - Step invoked erroneously, expected status "pending" or "running", got "${step.status}" instead, skipping execution`);
132
+ span?.setAttributes({
133
+ ...Attribute.StepSkipped(true),
134
+ ...Attribute.StepSkipReason(step.status),
135
+ });
136
+ // There's a chance that a step terminates correctly, but the underlying process
137
+ // fails or gets killed before the stepEntrypoint has a chance to re-enqueue the run.
138
+ // The queue lease expires and stepEntrypoint again, which leads us here, so
139
+ // we optimistically re-enqueue the workflow if the step is in a terminal state,
140
+ // under the assumption that this edge case happened.
141
+ // Until we move to atomic entity/event updates (World V2), there _could_ be an edge case
142
+ // where the we execute this code based on the `step` entity status, but the runtime
143
+ // failed to create the `step_completed` event (due to failing between step and event update),
144
+ // in which case, this might lead to an infinite loop.
145
+ // https://vercel.slack.com/archives/C09125LC4AX/p1765313809066679
146
+ const isTerminalStep = [
147
+ 'completed',
148
+ 'failed',
149
+ 'cancelled',
150
+ ].includes(step.status);
151
+ if (isTerminalStep) {
152
+ await queueMessage(world, `__wkf_workflow_${workflowName}`, {
153
+ runId: workflowRunId,
154
+ traceCarrier: await serializeTraceCarrier(),
155
+ requestedAt: new Date(),
156
+ });
157
+ }
158
+ return;
159
+ }
160
+ await world.events.create(workflowRunId, {
161
+ eventType: 'step_started', // TODO: Replace with 'step_retrying'
162
+ correlationId: stepId,
163
+ });
164
+ step = await world.steps.update(workflowRunId, stepId, {
165
+ attempt,
166
+ status: 'running',
167
+ });
168
+ if (!step.startedAt) {
169
+ throw new WorkflowRuntimeError(`Step "${stepId}" has no "startedAt" timestamp`);
170
+ }
171
+ // Hydrate the step input arguments, closure variables, and thisVal
172
+ const ops = [];
173
+ const hydratedInput = hydrateStepArguments(step.input, ops, workflowRunId);
174
+ const args = hydratedInput.args;
175
+ const thisVal = hydratedInput.thisVal ?? null;
176
+ span?.setAttributes({
177
+ ...Attribute.StepArgumentsCount(args.length),
178
+ });
179
+ result = await contextStorage.run({
180
+ stepMetadata: {
181
+ stepId,
182
+ stepStartedAt: new Date(+step.startedAt),
183
+ attempt,
184
+ },
185
+ workflowMetadata: {
186
+ workflowRunId,
187
+ workflowStartedAt: new Date(+workflowStartedAt),
188
+ // TODO: there should be a getUrl method on the world interface itself. This
189
+ // solution only works for vercel + local worlds.
190
+ url: process.env.VERCEL_URL
191
+ ? `https://${process.env.VERCEL_URL}`
192
+ : `http://localhost:${port ?? 3000}`,
193
+ },
194
+ ops,
195
+ closureVars: hydratedInput.closureVars,
196
+ }, () => stepFn.apply(thisVal, args));
197
+ // NOTE: None of the code from this point is guaranteed to run
198
+ // Since the step might fail or cause a function timeout and the process might be SIGKILL'd
199
+ // The workflow runtime must be resilient to the below code not executing on a failed step
200
+ result = dehydrateStepReturnValue(result, ops, workflowRunId);
201
+ waitUntil(Promise.all(ops).catch((err) => {
202
+ // Ignore expected client disconnect errors (e.g., browser refresh during streaming)
203
+ const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
204
+ if (!isAbortError)
205
+ throw err;
206
+ }));
207
+ // Mark the step as completed first. This order is important. If a concurrent
208
+ // execution marked the step as complete, this request should throw, and
209
+ // this prevent the step_completed event in the event log
210
+ // TODO: this should really be atomic and handled by the world
211
+ await world.steps.update(workflowRunId, stepId, {
212
+ status: 'completed',
213
+ output: result,
214
+ });
215
+ // Then, append the event log with the step result
216
+ await world.events.create(workflowRunId, {
217
+ eventType: 'step_completed',
218
+ correlationId: stepId,
219
+ eventData: {
220
+ result: result,
221
+ },
222
+ });
223
+ span?.setAttributes({
224
+ ...Attribute.StepStatus('completed'),
225
+ ...Attribute.StepResultType(typeof result),
226
+ });
227
+ }
228
+ catch (err) {
229
+ span?.setAttributes({
230
+ ...Attribute.StepErrorName(getErrorName(err)),
231
+ ...Attribute.StepErrorMessage(String(err)),
232
+ });
233
+ if (WorkflowAPIError.is(err)) {
234
+ if (err.status === 410) {
235
+ // Workflow has already completed, so no-op
236
+ console.warn(`Workflow run "${workflowRunId}" has already completed, skipping step "${stepId}": ${err.message}`);
237
+ return;
238
+ }
239
+ }
240
+ if (FatalError.is(err)) {
241
+ const errorStack = getErrorStack(err);
242
+ const stackLines = errorStack.split('\n').slice(0, 4);
243
+ console.error(`[Workflows] "${workflowRunId}" - Encountered \`FatalError\` while executing step "${stepName}":\n > ${stackLines.join('\n > ')}\n\nBubbling up error to parent workflow`);
244
+ // Fatal error - store the error in the event log and re-invoke the workflow
245
+ await world.events.create(workflowRunId, {
246
+ eventType: 'step_failed',
247
+ correlationId: stepId,
248
+ eventData: {
249
+ error: String(err),
250
+ stack: errorStack,
251
+ fatal: true,
252
+ },
253
+ });
254
+ await world.steps.update(workflowRunId, stepId, {
255
+ status: 'failed',
256
+ error: {
257
+ message: err.message || String(err),
258
+ stack: errorStack,
259
+ // TODO: include error codes when we define them
260
+ },
261
+ });
262
+ span?.setAttributes({
263
+ ...Attribute.StepStatus('failed'),
264
+ ...Attribute.StepFatalError(true),
265
+ });
266
+ }
267
+ else {
268
+ const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
269
+ span?.setAttributes({
270
+ ...Attribute.StepAttempt(attempt),
271
+ ...Attribute.StepMaxRetries(maxRetries),
272
+ });
273
+ // Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
274
+ if (attempt >= maxRetries + 1) {
275
+ // Max retries reached
276
+ const errorStack = getErrorStack(err);
277
+ const stackLines = errorStack.split('\n').slice(0, 4);
278
+ const retryCount = attempt - 1;
279
+ console.error(`[Workflows] "${workflowRunId}" - Encountered \`Error\` while executing step "${stepName}" (attempt ${attempt}, ${retryCount} ${pluralize('retry', 'retries', retryCount)}):\n > ${stackLines.join('\n > ')}\n\n Max retries reached\n Bubbling error to parent workflow`);
280
+ const errorMessage = `Step "${stepName}" failed after ${maxRetries} ${pluralize('retry', 'retries', maxRetries)}: ${String(err)}`;
281
+ await world.events.create(workflowRunId, {
282
+ eventType: 'step_failed',
283
+ correlationId: stepId,
284
+ eventData: {
285
+ error: errorMessage,
286
+ stack: errorStack,
287
+ fatal: true,
288
+ },
289
+ });
290
+ await world.steps.update(workflowRunId, stepId, {
291
+ status: 'failed',
292
+ error: {
293
+ message: errorMessage,
294
+ stack: errorStack,
295
+ },
296
+ });
297
+ span?.setAttributes({
298
+ ...Attribute.StepStatus('failed'),
299
+ ...Attribute.StepRetryExhausted(true),
300
+ });
301
+ }
302
+ else {
303
+ // Not at max retries yet - log as a retryable error
304
+ if (RetryableError.is(err)) {
305
+ console.warn(`[Workflows] "${workflowRunId}" - Encountered \`RetryableError\` while executing step "${stepName}" (attempt ${attempt}):\n > ${String(err.message)}\n\n This step has failed but will be retried`);
306
+ }
307
+ else {
308
+ const stackLines = getErrorStack(err).split('\n').slice(0, 4);
309
+ console.error(`[Workflows] "${workflowRunId}" - Encountered \`Error\` while executing step "${stepName}" (attempt ${attempt}):\n > ${stackLines.join('\n > ')}\n\n This step has failed but will be retried`);
310
+ }
311
+ await world.events.create(workflowRunId, {
312
+ eventType: 'step_failed',
313
+ correlationId: stepId,
314
+ eventData: {
315
+ error: String(err),
316
+ stack: getErrorStack(err),
317
+ },
318
+ });
319
+ await world.steps.update(workflowRunId, stepId, {
320
+ status: 'pending', // TODO: Should be "retrying" once we have that status
321
+ ...(RetryableError.is(err) && {
322
+ retryAfter: err.retryAfter,
323
+ }),
324
+ });
325
+ const timeoutSeconds = Math.max(1, RetryableError.is(err)
326
+ ? Math.ceil((+err.retryAfter.getTime() - Date.now()) / 1000)
327
+ : 1);
328
+ span?.setAttributes({
329
+ ...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
330
+ ...Attribute.StepRetryWillRetry(true),
331
+ });
332
+ // It's a retryable error - so have the queue keep the message visible
333
+ // so that it gets retried.
334
+ return { timeoutSeconds };
335
+ }
336
+ }
337
+ }
338
+ await queueMessage(world, `__wkf_workflow_${workflowName}`, {
339
+ runId: workflowRunId,
340
+ traceCarrier: await serializeTraceCarrier(),
341
+ requestedAt: new Date(),
342
+ });
343
+ });
344
+ });
345
+ });
346
+ /**
347
+ * A single route that handles any step execution request and routes to the
348
+ * appropriate step function. We may eventually want to create different bundles
349
+ * for each step, this is temporary.
350
+ */
351
+ export const stepEntrypoint =
352
+ /* @__PURE__ */ withHealthCheck(stepHandler);
353
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3RlcC1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQ0wsVUFBVSxFQUNWLGNBQWMsRUFDZCxnQkFBZ0IsRUFDaEIsb0JBQW9CLEdBQ3JCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFaEQsT0FBTyxFQUNMLHdCQUF3QixFQUN4QixvQkFBb0IsR0FDckIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDNUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQ0wsV0FBVyxFQUNYLG9CQUFvQixFQUNwQixxQkFBcUIsRUFDckIsS0FBSyxFQUNMLGdCQUFnQixHQUNqQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFELE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsd0JBQXdCLEVBQ3hCLHVCQUF1QixFQUN2QixZQUFZLEVBQ1osZUFBZSxHQUNoQixNQUFNLGNBQWMsQ0FBQztBQUN0QixPQUFPLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRXhELE1BQU0sd0JB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
@@ -0,0 +1,20 @@
1
+ import type { Span } from '@opentelemetry/api';
2
+ import type { World } from '@workflow/world';
3
+ import type { WorkflowSuspension } from '../global.js';
4
+ export interface SuspensionHandlerParams {
5
+ suspension: WorkflowSuspension;
6
+ world: World;
7
+ runId: string;
8
+ workflowName: string;
9
+ workflowStartedAt: number;
10
+ span?: Span;
11
+ }
12
+ export interface SuspensionHandlerResult {
13
+ timeoutSeconds?: number;
14
+ }
15
+ /**
16
+ * Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
17
+ * Hooks are processed first to prevent race conditions, then steps and waits in parallel.
18
+ */
19
+ export declare function handleSuspension({ suspension, world, runId, workflowName, workflowStartedAt, span, }: SuspensionHandlerParams): Promise<SuspensionHandlerResult>;
20
+ //# sourceMappingURL=suspension-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suspension-handler.d.ts","sourceRoot":"","sources":["../../src/runtime/suspension-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAIV,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAOtB,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAqLD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,UAAU,EACV,KAAK,EACL,KAAK,EACL,YAAY,EACZ,iBAAiB,EACjB,IAAI,GACL,EAAE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAwE5D"}