@@ -318,13 +318,16 @@ def test_retried_step(var: str) -> str:
318318
319319def test_recovery_workflow (dbos : DBOS ) -> None :
320320 txn_counter : int = 0
321+ txn_return_none_counter : int = 0
321322 wf_counter : int = 0
322323
323324 @DBOS .workflow ()
324325 def test_workflow (var : str , var2 : str ) -> str :
325326 nonlocal wf_counter
326327 wf_counter += 1
327328 res = test_transaction (var2 )
329+ should_be_none = test_transaction_return_none ()
330+ assert should_be_none is None
328331 return res + var
329332
330333 @DBOS .transaction ()
@@ -334,6 +337,13 @@ def test_transaction(var2: str) -> str:
334337 txn_counter += 1
335338 return var2 + str (rows [0 ][0 ])
336339
340+ @DBOS .transaction ()
341+ def test_transaction_return_none () -> None :
342+ nonlocal txn_return_none_counter
343+ DBOS .sql_session .execute (sa .text ("SELECT 1" )).fetchall ()
344+ txn_return_none_counter += 1
345+ return
346+
337347 wfuuid = str (uuid .uuid4 ())
338348 with SetWorkflowID (wfuuid ):
339349 assert test_workflow ("bob" , "bob" ) == "bob1bob"
@@ -367,6 +377,7 @@ def test_transaction(var2: str) -> str:
367377 assert workflow_handles [0 ].get_result () == "bob1bob"
368378 assert wf_counter == 2
369379 assert txn_counter == 1
380+ assert txn_return_none_counter == 1
370381
371382 # Test that there was a recovery attempt of this
372383 stat = workflow_handles [0 ].get_status ()
@@ -382,7 +393,8 @@ def test_recovery_workflow_step(dbos: DBOS) -> None:
382393 def test_workflow (var : str , var2 : str ) -> str :
383394 nonlocal wf_counter
384395 wf_counter += 1
385- test_step (var2 )
396+ should_be_none = test_step (var2 )
397+ assert should_be_none is None
386398 return var
387399
388400 @DBOS .step ()
@@ -432,6 +444,63 @@ def test_step(var2: str) -> None:
432444 assert stat .recovery_attempts == 1
433445
434446
447+ def test_workflow_returns_none (dbos : DBOS ) -> None :
448+ wf_counter : int = 0
449+
450+ @DBOS .workflow ()
451+ def test_workflow (var : str , var2 : str ) -> None :
452+ nonlocal wf_counter
453+ wf_counter += 1
454+ assert var == var2 == "bob"
455+ return
456+
457+ wfuuid = str (uuid .uuid4 ())
458+ with SetWorkflowID (wfuuid ):
459+ assert test_workflow ("bob" , "bob" ) is None
460+ assert wf_counter == 1
461+
462+ dbos ._sys_db .wait_for_buffer_flush ()
463+ with SetWorkflowID (wfuuid ):
464+ assert test_workflow ("bob" , "bob" ) is None
465+ assert wf_counter == 2
466+
467+ handle : WorkflowHandle [None ] = DBOS .retrieve_workflow (wfuuid )
468+ assert handle .get_result () == None
469+ assert wf_counter == 2
470+
471+ # Change the workflow status to pending
472+ dbos ._sys_db .update_workflow_status (
473+ {
474+ "workflow_uuid" : wfuuid ,
475+ "status" : "PENDING" ,
476+ "name" : test_workflow .__qualname__ ,
477+ "class_name" : None ,
478+ "config_name" : None ,
479+ "output" : None ,
480+ "error" : None ,
481+ "executor_id" : None ,
482+ "app_id" : None ,
483+ "app_version" : None ,
484+ "request" : None ,
485+ "recovery_attempts" : None ,
486+ "authenticated_user" : None ,
487+ "authenticated_roles" : None ,
488+ "assumed_role" : None ,
489+ "queue_name" : None ,
490+ }
491+ )
492+
493+ workflow_handles = DBOS .recover_pending_workflows ()
494+ assert len (workflow_handles ) == 1
495+ assert workflow_handles [0 ].get_result () is None
496+ assert wf_counter == 3
497+
498+ # Test that there was a recovery attempt of this
499+ stat = workflow_handles [0 ].get_status ()
500+ assert stat
501+ assert stat .recovery_attempts == 1
502+
503+
435504def test_recovery_temp_workflow (dbos : DBOS ) -> None :
436505 txn_counter : int = 0
437506
0 commit comments