@@ -798,6 +798,106 @@ func TestChildWorkflow(t *testing.T) {
798798 t .Fatalf ("expected second step child workflow ID to be %s, got %s" , customChildID , steps [1 ].ChildWorkflowID )
799799 }
800800 })
801+
802+ t .Run ("RecoveredChildWorkflowPollingHandle" , func (t * testing.T ) {
803+ pollingHandleStartEvent := NewEvent ()
804+ pollingHandleCompleteEvent := NewEvent ()
805+ knownChildID := "known-child-workflow-id"
806+ knownParentID := "known-parent-workflow-id"
807+ counter := 0
808+
809+ // Simple child workflow that returns a result
810+ pollingHandleChildWf := func (dbosCtx DBOSContext , input string ) (string , error ) {
811+ // Signal the child workflow is started
812+ pollingHandleStartEvent .Set ()
813+ // Wait
814+ pollingHandleCompleteEvent .Wait ()
815+ return input + "-result" , nil
816+ }
817+ RegisterWorkflow (dbosCtx , pollingHandleChildWf )
818+
819+ pollingHandleParentWf := func (ctx DBOSContext , input string ) (string , error ) {
820+ counter ++
821+
822+ // Run child workflow with a known ID
823+ childHandle , err := RunAsWorkflow (ctx , pollingHandleChildWf , "child-input" , WithWorkflowID (knownChildID ))
824+ if err != nil {
825+ return "" , fmt .Errorf ("failed to run child workflow: %w" , err )
826+ }
827+
828+ switch counter {
829+ case 1 :
830+ // First handle will be a direct handle
831+ _ , ok := childHandle .(* workflowHandle [string ])
832+ if ! ok {
833+ return "" , fmt .Errorf ("expected child handle to be of type workflowDirectHandle, got %T" , childHandle )
834+ }
835+ case 2 :
836+ // Second handle will be a polling handle
837+ _ , ok := childHandle .(* workflowPollingHandle [string ])
838+ if ! ok {
839+ return "" , fmt .Errorf ("expected recovered child handle to be of type workflowPollingHandle, got %T" , childHandle )
840+ }
841+ }
842+
843+ result , err := childHandle .GetResult ()
844+ if err != nil {
845+ return "" , fmt .Errorf ("failed to get result from child workflow: %w" , err )
846+ }
847+ return result , nil
848+ }
849+ RegisterWorkflow (dbosCtx , pollingHandleParentWf )
850+
851+ // Execute parent workflow - it will block after starting the child
852+ parentHandle , err := RunAsWorkflow (dbosCtx , pollingHandleParentWf , "parent-input" , WithWorkflowID (knownParentID ))
853+ if err != nil {
854+ t .Fatalf ("failed to start parent workflow: %v" , err )
855+ }
856+
857+ // Wait for the child workflow to start
858+ pollingHandleStartEvent .Wait ()
859+
860+ // Recover pending workflows - this should give us both parent and child handles
861+ recoveredHandles , err := recoverPendingWorkflows (dbosCtx .(* dbosContext ), []string {"local" })
862+ if err != nil {
863+ t .Fatalf ("failed to recover pending workflows: %v" , err )
864+ }
865+
866+ // Should have recovered both parent and child workflows
867+ if len (recoveredHandles ) != 2 {
868+ t .Fatalf ("expected 2 recovered handles (parent and child), got %d" , len (recoveredHandles ))
869+ }
870+
871+ // Find the child handle and verify it's a polling handle with the correct ID
872+ var childRecoveredHandle WorkflowHandle [any ]
873+ for _ , handle := range recoveredHandles {
874+ if handle .GetWorkflowID () == knownChildID {
875+ childRecoveredHandle = handle
876+ break
877+ }
878+ }
879+
880+ if childRecoveredHandle == nil {
881+ t .Fatalf ("failed to find recovered child workflow handle with ID %s" , knownChildID )
882+ }
883+
884+ // Complete both workflows
885+ pollingHandleCompleteEvent .Set ()
886+ result , err := parentHandle .GetResult ()
887+ if err != nil {
888+ t .Fatalf ("failed to get result from original parent workflow: %v" , err )
889+ }
890+ if result != "child-input-result" {
891+ t .Fatalf ("expected result 'child-input-result', got '%s'" , result )
892+ }
893+ childResult , err := childRecoveredHandle .GetResult ()
894+ if err != nil {
895+ t .Fatalf ("failed to get result from recovered child handle: %v" , err )
896+ }
897+ if childResult != result {
898+ t .Fatalf ("expected child result '%s', got '%s'" , result , childResult )
899+ }
900+ })
801901}
802902
803903// Idempotency workflows moved to test functions
0 commit comments