@@ -2040,6 +2040,143 @@ func (ts *IntegrationTestSuite) TestResetWorkflowExecution() {
2040
2040
ts .Equal (originalResult , newResult )
2041
2041
}
2042
2042
2043
+ // TestResetWorkflowExecutionWithChildren tests the behavior of child workflow ID generation when a workflow with children is reset.
2044
+ // It repeatedly resets the workflow at different points in its execution and verifies that the child workflow IDs are generated correctly.
2045
+ func (ts * IntegrationTestSuite ) TestResetWorkflowExecutionWithChildren () {
2046
+ wfID := "reset-workflow-with-children"
2047
+ ctx , cancel := context .WithTimeout (context .Background (), ctxTimeout )
2048
+ defer cancel ()
2049
+
2050
+ // Start a workflow with 3 children.
2051
+ options := ts .startWorkflowOptions (wfID )
2052
+ run , err := ts .client .ExecuteWorkflow (ctx , options , ts .workflows .WorkflowWithChildren )
2053
+ ts .NoError (err )
2054
+ var originalResult string
2055
+ err = run .Get (ctx , & originalResult )
2056
+ ts .NoError (err )
2057
+
2058
+ // save child init childIDs for later comparison.
2059
+ childIDs := ts .getChildWFIDsFromHistory (ctx , wfID , run .GetRunID ())
2060
+ ts .Len (childIDs , 3 )
2061
+ child1IDBeforeReset := childIDs [0 ]
2062
+ child2IDBeforeReset := childIDs [1 ]
2063
+ child3IDBeforeReset := childIDs [2 ]
2064
+
2065
+ resetRequest := & workflowservice.ResetWorkflowExecutionRequest {
2066
+ Namespace : ts .config .Namespace ,
2067
+ WorkflowExecution : & commonpb.WorkflowExecution {
2068
+ WorkflowId : wfID ,
2069
+ RunId : run .GetRunID (),
2070
+ },
2071
+ Reason : "integration test" ,
2072
+ }
2073
+ // (reset #1) - resetting the workflow execution before both child workflows are started.
2074
+ resetRequest .RequestId = "reset-request-1"
2075
+ resetRequest .WorkflowTaskFinishEventId = 4
2076
+ resp , err := ts .client .ResetWorkflowExecution (context .Background (), resetRequest )
2077
+ ts .NoError (err )
2078
+ // Wait for the new run to complete.
2079
+ var resultAfterReset1 string
2080
+ err = ts .client .GetWorkflow (context .Background (), wfID , resp .GetRunId ()).Get (ctx , & resultAfterReset1 )
2081
+ ts .NoError (err )
2082
+ ts .Equal (originalResult , resultAfterReset1 )
2083
+
2084
+ childIDsAfterReset1 := ts .getChildWFIDsFromHistory (ctx , wfID , resp .GetRunId ())
2085
+ ts .Len (childIDsAfterReset1 , 3 )
2086
+ // All 3 child workflow IDs should be different after reset.
2087
+ ts .NotEqual (child1IDBeforeReset , childIDsAfterReset1 [0 ])
2088
+ ts .NotEqual (child2IDBeforeReset , childIDsAfterReset1 [1 ])
2089
+ ts .NotEqual (child3IDBeforeReset , childIDsAfterReset1 [2 ])
2090
+
2091
+ // (reset #2) - resetting the new workflow execution after child-1 but before child-2
2092
+ resetRequest .RequestId = "reset-request-2"
2093
+ resetRequest .WorkflowExecution .RunId = resp .GetRunId ()
2094
+ resetRequest .WorkflowTaskFinishEventId = ts .getWorkflowTaskFinishEventIdAfterChild (ctx , wfID , resp .GetRunId (), childIDsAfterReset1 [0 ])
2095
+ resp , err = ts .client .ResetWorkflowExecution (context .Background (), resetRequest )
2096
+ ts .NoError (err )
2097
+ // Wait for the new run to complete.
2098
+ var resultAfterReset2 string
2099
+ err = ts .client .GetWorkflow (context .Background (), wfID , resp .GetRunId ()).Get (ctx , & resultAfterReset2 )
2100
+ ts .NoError (err )
2101
+ ts .Equal (originalResult , resultAfterReset2 )
2102
+
2103
+ childIDsAfterReset2 := ts .getChildWFIDsFromHistory (ctx , wfID , resp .GetRunId ())
2104
+ ts .Len (childIDsAfterReset2 , 3 )
2105
+ ts .Equal (childIDsAfterReset1 [0 ], childIDsAfterReset2 [0 ]) // child-1 should be the same as before reset.
2106
+ ts .NotEqual (childIDsAfterReset1 [1 ], childIDsAfterReset2 [1 ]) // child-2 should be different after reset.
2107
+ ts .NotEqual (childIDsAfterReset1 [2 ], childIDsAfterReset2 [2 ]) // Child-3 should be different after reset.
2108
+
2109
+ // (reset #3) - resetting the new workflow execution after child-2 but before child-3
2110
+ resetRequest .RequestId = "reset-request-3"
2111
+ resetRequest .WorkflowExecution .RunId = resp .GetRunId ()
2112
+ resetRequest .WorkflowTaskFinishEventId = ts .getWorkflowTaskFinishEventIdAfterChild (ctx , wfID , resp .GetRunId (), childIDsAfterReset2 [1 ])
2113
+ resp , err = ts .client .ResetWorkflowExecution (context .Background (), resetRequest )
2114
+ ts .NoError (err )
2115
+ // Wait for the new run to complete.
2116
+ var resultAfterReset3 string
2117
+ err = ts .client .GetWorkflow (context .Background (), wfID , resp .GetRunId ()).Get (ctx , & resultAfterReset3 )
2118
+ ts .NoError (err )
2119
+ ts .Equal (originalResult , resultAfterReset3 )
2120
+
2121
+ childIDsAfterReset3 := ts .getChildWFIDsFromHistory (ctx , wfID , resp .GetRunId ())
2122
+ ts .Len (childIDsAfterReset3 , 3 )
2123
+ // child-1 & child-2 workflow IDs should be the same as before reset. Child-3 should be different.
2124
+ ts .Equal (childIDsAfterReset2 [0 ], childIDsAfterReset3 [0 ])
2125
+ ts .Equal (childIDsAfterReset2 [1 ], childIDsAfterReset3 [1 ])
2126
+ ts .NotEqual (childIDsAfterReset2 [2 ], childIDsAfterReset3 [2 ])
2127
+
2128
+ // (reset #3) - resetting the new workflow execution one last time after child-3
2129
+ // This should successfully replay all child events and not change the child workflow IDs from previous run.
2130
+ resetRequest .RequestId = "reset-request-4"
2131
+ resetRequest .WorkflowExecution .RunId = resp .GetRunId ()
2132
+ resetRequest .WorkflowTaskFinishEventId = ts .getWorkflowTaskFinishEventIdAfterChild (ctx , wfID , resp .GetRunId (), childIDsAfterReset3 [2 ])
2133
+ resp , err = ts .client .ResetWorkflowExecution (context .Background (), resetRequest )
2134
+ ts .NoError (err )
2135
+ childIDsFinal := ts .getChildWFIDsFromHistory (ctx , wfID , resp .GetRunId ())
2136
+ ts .Len (childIDsFinal , 3 )
2137
+ ts .Equal (childIDsAfterReset3 [0 ], childIDsFinal [0 ])
2138
+ ts .Equal (childIDsAfterReset3 [1 ], childIDsFinal [1 ])
2139
+ ts .Equal (childIDsAfterReset3 [2 ], childIDsFinal [2 ])
2140
+ }
2141
+
2142
+ func (ts * IntegrationTestSuite ) getChildWFIDsFromHistory (ctx context.Context , wfID string , runID string ) []string {
2143
+ iter := ts .client .GetWorkflowHistory (ctx , wfID , runID , false , enumspb .HISTORY_EVENT_FILTER_TYPE_ALL_EVENT )
2144
+ var childIDs []string
2145
+ for iter .HasNext () {
2146
+ event , err1 := iter .Next ()
2147
+ if err1 != nil {
2148
+ break
2149
+ }
2150
+ if event .GetEventType () == enumspb .EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED {
2151
+ childIDs = append (childIDs , event .GetStartChildWorkflowExecutionInitiatedEventAttributes ().GetWorkflowId ())
2152
+ }
2153
+ }
2154
+ return childIDs
2155
+ }
2156
+
2157
+ func (ts * IntegrationTestSuite ) getWorkflowTaskFinishEventIdAfterChild (ctx context.Context , wfID string , runID string , childID string ) int64 {
2158
+ iter := ts .client .GetWorkflowHistory (ctx , wfID , runID , false , enumspb .HISTORY_EVENT_FILTER_TYPE_ALL_EVENT )
2159
+ childFound := false
2160
+ for iter .HasNext () {
2161
+ event , err := iter .Next ()
2162
+ if err != nil {
2163
+ break
2164
+ }
2165
+ if event .GetEventType () == enumspb .EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_COMPLETED {
2166
+ if event .GetChildWorkflowExecutionCompletedEventAttributes ().GetWorkflowExecution ().GetWorkflowId () == childID {
2167
+ childFound = true
2168
+ }
2169
+ }
2170
+ if ! childFound {
2171
+ continue
2172
+ }
2173
+ if event .GetEventType () == enumspb .EVENT_TYPE_WORKFLOW_TASK_COMPLETED {
2174
+ return event .GetEventId ()
2175
+ }
2176
+ }
2177
+ return 0
2178
+ }
2179
+
2043
2180
func (ts * IntegrationTestSuite ) TestResetWorkflowExecutionWithUpdate () {
2044
2181
ctx := context .Background ()
2045
2182
wfId := "reset-workflow-execution-with-update"
0 commit comments