File tree Expand file tree Collapse file tree 2 files changed +50
-1
lines changed
rivetkit-typescript/packages/workflow-engine Expand file tree Collapse file tree 2 files changed +50
-1
lines changed Original file line number Diff line number Diff line change @@ -380,12 +380,27 @@ export class WorkflowContextImpl implements WorkflowContextInterface {
380380 return stepData . output as T ;
381381 }
382382
383- // Check if we should retry
383+ // Check if we should retry.
384+ //
385+ // Important: steps that *return undefined* (i.e. "void" steps) are valid and
386+ // must still be treated as completed on restart. Since JSON omits properties
387+ // with value `undefined`, we cannot rely on `stepData.output !== undefined`
388+ // to determine completion. Prefer metadata.status for completion tracking.
384389 const metadata = await loadMetadata (
385390 this . storage ,
386391 this . driver ,
387392 existing . id ,
388393 ) ;
394+
395+ if ( metadata . status === "completed" ) {
396+ this . log ( "debug" , {
397+ msg : "replaying completed step from metadata" ,
398+ step : config . name ,
399+ key,
400+ } ) ;
401+ return stepData . output as T ;
402+ }
403+
389404 const maxRetries = config . maxRetries ?? DEFAULT_MAX_RETRIES ;
390405
391406 if ( metadata . attempts >= maxRetries ) {
Original file line number Diff line number Diff line change @@ -72,6 +72,40 @@ for (const mode of modes) {
7272 expect ( callCount ) . toBe ( 1 ) ;
7373 } ) ;
7474
75+ it ( "should treat void step outputs as completed on restart" , async ( ) => {
76+ let callCount = 0 ;
77+
78+ const workflow = async ( ctx : WorkflowContextInterface ) => {
79+ await ctx . step ( "void-step" , async ( ) => {
80+ callCount += 1 ;
81+ // return undefined (void)
82+ } ) ;
83+ return "done" ;
84+ } ;
85+
86+ const first = await runWorkflow (
87+ "wf-void" ,
88+ workflow ,
89+ undefined ,
90+ driver ,
91+ { mode } ,
92+ ) . result ;
93+ expect ( first . state ) . toBe ( "completed" ) ;
94+ expect ( first . output ) . toBe ( "done" ) ;
95+ expect ( callCount ) . toBe ( 1 ) ;
96+
97+ const second = await runWorkflow (
98+ "wf-void" ,
99+ workflow ,
100+ undefined ,
101+ driver ,
102+ { mode } ,
103+ ) . result ;
104+ expect ( second . state ) . toBe ( "completed" ) ;
105+ expect ( second . output ) . toBe ( "done" ) ;
106+ expect ( callCount ) . toBe ( 1 ) ;
107+ } ) ;
108+
75109 it ( "should execute multiple steps in sequence" , async ( ) => {
76110 const workflow = async ( ctx : WorkflowContextInterface ) => {
77111 const a = await ctx . step ( "step-a" , async ( ) => 1 ) ;
You can’t perform that action at this time.
0 commit comments