@rivetkit/workflow-engine 2.3.18 → 2.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -12,7 +12,16 @@ export {
12
12
  WorkflowContextImpl,
13
13
  } from "./context.js";
14
14
  // Driver
15
- export type { EngineDriver, KVEntry, KVWrite } from "./driver.js";
15
+ export type {
16
+ EngineDriver,
17
+ KVEntry,
18
+ KVWrite,
19
+ WorkflowOutcome,
20
+ WorkflowSpan,
21
+ WorkflowStepOutcome,
22
+ WorkflowStepSpan,
23
+ WorkflowTelemetryDriver,
24
+ } from "./driver.js";
16
25
  export { extractErrorInfo } from "./error-utils.js";
17
26
  // Errors
18
27
  export {
@@ -143,7 +152,7 @@ import {
143
152
  } from "../schemas/serde.js";
144
153
  import { type RollbackAction, WorkflowContextImpl } from "./context.js";
145
154
  // Main workflow runner
146
- import type { EngineDriver } from "./driver.js";
155
+ import type { EngineDriver, WorkflowOutcome, WorkflowSpan } from "./driver.js";
147
156
  import {
148
157
  extractErrorInfo,
149
158
  getErrorEventTag,
@@ -288,6 +297,7 @@ async function executeRollback<TInput, TOutput>(
288
297
  historyNotifier?: HistoryNotifier,
289
298
  onError?: RunWorkflowOptions["onError"],
290
299
  logger?: Logger,
300
+ runSpan?: WorkflowSpan,
291
301
  ): Promise<void> {
292
302
  const rollbackActions: RollbackAction[] = [];
293
303
  const ctx = new WorkflowContextImpl(
@@ -303,6 +313,8 @@ async function executeRollback<TInput, TOutput>(
303
313
  historyNotifier,
304
314
  onError,
305
315
  logger,
316
+ undefined,
317
+ runSpan,
306
318
  );
307
319
 
308
320
  try {
@@ -511,16 +523,19 @@ async function executeLiveWorkflow<TInput, TOutput>(
511
523
  let lastResult: WorkflowResult<TOutput> | undefined;
512
524
 
513
525
  while (true) {
514
- const result = await executeWorkflow(
515
- workflowId,
516
- workflowFn,
517
- input,
518
- driver,
519
- messageDriver,
520
- abortController,
521
- onHistoryUpdated,
522
- onError,
523
- logger,
526
+ const result = await traceRun(driver, (runSpan) =>
527
+ executeWorkflow(
528
+ workflowId,
529
+ workflowFn,
530
+ input,
531
+ driver,
532
+ messageDriver,
533
+ abortController,
534
+ onHistoryUpdated,
535
+ onError,
536
+ logger,
537
+ runSpan,
538
+ ),
524
539
  );
525
540
  lastResult = result;
526
541
 
@@ -642,16 +657,19 @@ export function runWorkflow<TInput, TOutput>(
642
657
  options.onError,
643
658
  logger,
644
659
  )
645
- : executeWorkflow(
646
- workflowId,
647
- workflowFn,
648
- input,
649
- driver,
650
- messageDriver,
651
- abortController,
652
- options.onHistoryUpdated,
653
- options.onError,
654
- logger,
660
+ : traceRun(driver, (runSpan) =>
661
+ executeWorkflow(
662
+ workflowId,
663
+ workflowFn,
664
+ input,
665
+ driver,
666
+ messageDriver,
667
+ abortController,
668
+ options.onHistoryUpdated,
669
+ options.onError,
670
+ logger,
671
+ runSpan,
672
+ ),
655
673
  );
656
674
 
657
675
  return {
@@ -886,6 +904,49 @@ function findReplayBoundaryEntry(
886
904
  return boundary;
887
905
  }
888
906
 
907
+ function runOutcomeFromState(state: WorkflowState): WorkflowOutcome {
908
+ switch (state) {
909
+ case "completed":
910
+ return "completed";
911
+ case "sleeping":
912
+ return "sleeping";
913
+ case "failed":
914
+ return "failed";
915
+ case "cancelled":
916
+ return "cancelled";
917
+ case "pending":
918
+ case "running":
919
+ case "rolling_back":
920
+ return "evicted";
921
+ }
922
+ }
923
+
924
+ /** Internal: Report one workflow run to the driver's telemetry, when it has any. */
925
+ async function traceRun<TOutput>(
926
+ driver: EngineDriver,
927
+ run: (span?: WorkflowSpan) => Promise<WorkflowResult<TOutput>>,
928
+ ): Promise<WorkflowResult<TOutput>> {
929
+ if (!driver.telemetry) {
930
+ return await run();
931
+ }
932
+
933
+ const span = await driver.telemetry.startSpan();
934
+ let outcome: WorkflowOutcome = "failed";
935
+ try {
936
+ const result = await span.run(() => run(span));
937
+ outcome = runOutcomeFromState(result.state);
938
+ return result;
939
+ } catch (error) {
940
+ // A run throws EvictedError only when the workflow was already cancelled.
941
+ if (error instanceof EvictedError) {
942
+ outcome = "cancelled";
943
+ }
944
+ throw error;
945
+ } finally {
946
+ await span.finish(outcome);
947
+ }
948
+ }
949
+
889
950
  /**
890
951
  * Internal: Execute the workflow and return the result.
891
952
  */
@@ -899,6 +960,7 @@ async function executeWorkflow<TInput, TOutput>(
899
960
  onHistoryUpdated?: (history: WorkflowHistorySnapshot) => void,
900
961
  onError?: RunWorkflowOptions["onError"],
901
962
  logger?: Logger,
963
+ runSpan?: WorkflowSpan,
902
964
  ): Promise<WorkflowResult<TOutput>> {
903
965
  const storage = await loadStorage(driver);
904
966
  const historyNotifier: HistoryNotifier = onHistoryUpdated
@@ -953,6 +1015,7 @@ async function executeWorkflow<TInput, TOutput>(
953
1015
  historyNotifier,
954
1016
  onError,
955
1017
  logger,
1018
+ runSpan,
956
1019
  );
957
1020
  } catch (error) {
958
1021
  if (error instanceof EvictedError) {
@@ -986,6 +1049,8 @@ async function executeWorkflow<TInput, TOutput>(
986
1049
  historyNotifier,
987
1050
  onError,
988
1051
  logger,
1052
+ undefined,
1053
+ runSpan,
989
1054
  );
990
1055
 
991
1056
  storage.state = "running";
@@ -1064,6 +1129,7 @@ async function executeWorkflow<TInput, TOutput>(
1064
1129
  historyNotifier,
1065
1130
  onError,
1066
1131
  logger,
1132
+ runSpan,
1067
1133
  );
1068
1134
  } catch (rollbackError) {
1069
1135
  if (rollbackError instanceof EvictedError) {
package/src/keys.ts CHANGED
@@ -14,6 +14,7 @@ export const KEY_PREFIX = {
14
14
  HISTORY: 2, // History entries: [2, ...locationSegments]
15
15
  WORKFLOW: 3, // Workflow metadata: [3, field]
16
16
  ENTRY_METADATA: 4, // Entry metadata: [4, entryId]
17
+ // 5 is reserved for RivetKit's workflow trace context.
17
18
  } as const;
18
19
 
19
20
  // Workflow metadata field identifiers