Skip to content

Commit deb9821

Browse files
committed
Fail QueryWorkflow if last WorkflowTask failed
1 parent 11cef80 commit deb9821

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

service/history/api/queryworkflow/api.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ func Invoke(
115115
return nil, consts.ErrWorkflowTaskNotScheduled
116116
}
117117

118+
if mutableState.GetExecutionInfo().WorkflowTaskAttempt > 1 {
119+
// while workflow task is failing, the query to that workflow will also fail. Failing fast here to prevent wasting
120+
// resources to load history for a query that will fail.
121+
return nil, serviceerror.NewFailedPrecondition("Query has failed due to a failing workflow task")
122+
}
123+
118124
// There are two ways in which queries get dispatched to workflow worker. First, queries can be dispatched on workflow tasks.
119125
// These workflow tasks potentially contain new events and queries. The events are treated as coming before the query in time.
120126
// The second way in which queries are dispatched to workflow worker is directly through matching; in this approach queries can be

tests/query_workflow_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838

3939
"go.temporal.io/server/service/history/consts"
4040

41+
"go.temporal.io/api/serviceerror"
4142
"go.temporal.io/server/common/log/tag"
4243
)
4344

@@ -257,3 +258,38 @@ func (s *clientIntegrationSuite) TestQueryWorkflow_QueryBeforeStart() {
257258
// wait query
258259
wg.Wait()
259260
}
261+
262+
func (s *clientIntegrationSuite) TestQueryWorkflow_QueryFailedWorkflowTask() {
263+
264+
workflowFn := func(ctx workflow.Context) (string, error) {
265+
workflow.SetQueryHandler(ctx, "test", func() (string, error) {
266+
return "", nil
267+
})
268+
269+
// force workflow task to fail
270+
panic("Workflow failed")
271+
}
272+
273+
s.worker.RegisterWorkflow(workflowFn)
274+
275+
id := "test-query-failed-workflow-task"
276+
workflowOptions := sdkclient.StartWorkflowOptions{
277+
ID: id,
278+
TaskQueue: s.taskQueue,
279+
WorkflowRunTimeout: 20 * time.Second,
280+
}
281+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
282+
defer cancel()
283+
workflowRun, err := s.sdkClient.ExecuteWorkflow(ctx, workflowOptions, workflowFn)
284+
if err != nil {
285+
s.Logger.Fatal("Start workflow failed with err", tag.Error(err))
286+
}
287+
288+
s.NotNil(workflowRun)
289+
s.True(workflowRun.GetRunID() != "")
290+
291+
// wait for workflow to fail
292+
time.Sleep(time.Second * 5)
293+
_, err = s.sdkClient.QueryWorkflow(ctx, id, "", "test")
294+
s.IsType(&serviceerror.FailedPrecondition{}, err)
295+
}

0 commit comments

Comments
 (0)