Implement GetWorkflowExecutionResult#10173
Conversation
71e932b to
9ec54e6
Compare
9ec54e6 to
807f96b
Compare
| req.Service = cmp.Or(req.Service, "test-service") | ||
| req.Operation = cmp.Or(req.Operation, "test-operation") |
There was a problem hiding this comment.
opportunistic refactor from nexus_standalone_test.go, but maybe slightly overboard with still keeping these defaults here :) LMK if folks prefer to not have defaults at all
| leafErr := pollResp.GetFailure() | ||
| for leafErr.GetCause() != nil { | ||
| leafErr = leafErr.GetCause() | ||
| } | ||
| protorequire.ProtoEqual(s.T(), | ||
| &failurepb.Failure{Message: intentionalFailureMsg}, | ||
| leafErr, | ||
| protorequire.IgnoreFields("source", "stack_trace", "encoded_attributes", "application_failure_info"), | ||
| ) |
There was a problem hiding this comment.
this seemed slightly clunky to me but I wasn't sure there was another way to unwrap and assert on this base error, LMK if there is
|
|
||
| // Walk the CAN chain until we reach the head. At head, we will return the result of the head's workflow run, | ||
| // and optionally attach callbacks if hasCallbacks. | ||
| for range maxCANChainDepth { |
There was a problem hiding this comment.
This was what I did in my prototype, but I question if this is the right approach to have an arb. limit here. I wonder if we could be smarter but it would require a larger effort. I was thinking if we only support targeting the latest run ID then we don't need to tackle this problem yet.
There was a problem hiding this comment.
commenting for posterity per offline discussion: will always get result for latest (empty) run id for now to make this simpler
There was a problem hiding this comment.
should we remove the code if it's effectively dead?
There was a problem hiding this comment.
I think this code is already deleted
- Always default to latest runID (empty) - Incorporate latest API proto changes
| req.Service = cmp.Or(req.Service, "test-service") | ||
| req.Operation = cmp.Or(req.Operation, "test-operation") |
| if namespaceID == "" { | ||
| return nil, h.convertError(errNamespaceNotSet) | ||
| } |
There was a problem hiding this comment.
This is redundant; ValidateNamespaceUUID already contains that check.
| history := env.SdkClient().GetWorkflowHistory(env.Context(), run.GetID(), "", false, enumspb.HISTORY_EVENT_FILTER_TYPE_ALL_EVENT) | ||
| foundEvent := false | ||
| for history.HasNext() { | ||
| event, err := history.Next() | ||
| s.NoError(err) | ||
| if event.EventType != enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_OPTIONS_UPDATED { | ||
| continue | ||
| } | ||
| foundEvent = true | ||
| protorequire.ProtoSliceEqual(s.T(), links, event.Links) | ||
| } | ||
| s.True(foundEvent) |
There was a problem hiding this comment.
could use HistoryRequire's RequireHistoryEvent
| if err := validateRequestId(&request.RequestId, wh.config.MaxIDLengthLimit()); err != nil { | ||
| return nil, err | ||
| } | ||
|
|
There was a problem hiding this comment.
WDYT about adding this?
if req.GetExecution().GetRunId() != "" {
return nil, serviceerror.NewInvalidArgument("RunId is not supported")
}| // Write path: there are completion callbacks or links, and this workflow execution is running: | ||
| // 1. Attach callbacks and links via AddWorkflowExecutionOptionsUpdatedEvent | ||
| // 2. Set response for caller with backlinks | ||
| // 3. Return with Noop=false so the attachments get persisted. |
There was a problem hiding this comment.
create comments in this closure!
There was a problem hiding this comment.
I assumed you meant Return with Noop=false so the attachments get persisted. right above where it is
| testcore.WithDynamicConfig(dynamicconfig.EnableChasm, true), | ||
| testcore.WithDynamicConfig(nexusoperation.Enabled, true), | ||
| ) | ||
| } |
There was a problem hiding this comment.
inline if only used once?
| } | ||
| } | ||
|
|
||
| func newGetResultNexusEnv(t *testing.T, opts ...testcore.TestOption) *NexusTestEnv { |
There was a problem hiding this comment.
the other suites often follow the pattern of having a newTestEnv method
| // runViaCallerWF runs the scenario via a caller workflow that uses | ||
| // workflow.NewNexusClient to invoke the operation. The caller workflow itself is | ||
| // opaque about what target it's querying; that's wired into the handler. | ||
| func runViaCallerWF(s *NexusGetWorkflowResultTestSuite, spec *targetWFSpec) { |
There was a problem hiding this comment.
This can be a method, too (no?)
There was a problem hiding this comment.
I was running tests via a runner so had this as a helper so i pass down the right s. Elevated this and runViaStandalone(...) to be suite test functions, copying pattern from temporal/tests/task_queue_stats_test.go
| // Each test runs both WorkflowWrapped and Standalone subtests. | ||
| // ============================================================================= | ||
|
|
||
| func (s *NexusGetWorkflowResultTestSuite) TestGetResult() { |
There was a problem hiding this comment.
check out temporal/tests/task_queue_stats_test.go to do this a little better IMO by leveraging suites fully
| ) | ||
| } | ||
| return resp, nil | ||
| } |
There was a problem hiding this comment.
I think some of these code paths aren't tested; might be good to do (unit test is likely easier than func test)
There was a problem hiding this comment.
added service/history/api/getworkflowexecutionresult/api_test.go
| if err := validateRequestId(&request.RequestId, wh.config.MaxIDLengthLimit()); err != nil { | ||
| return nil, err | ||
| } | ||
| if request.GetExecution().GetRunId() != "" { |
There was a problem hiding this comment.
Why not support getting the result of a specific run id?
There was a problem hiding this comment.
Because if the workflow run continued as new we would have to follow continue as new errors to get the result
There was a problem hiding this comment.
I think we want to support the ability to follow continue as new errors. Also there's no guarantee that they want the result for the most recent run of a workflow. The user might not know if the run that they want was the most recent instance of a workflow.
What changed?
Server PR for API counterpart temporalio/api#778
This API allows users to get the result of a workflow execution and optionally attach callbacks to be fired when the workflow completes (if the workflow is running). It follows continue-as-new chain up to
GetWorkflowExecutionResultMaxCANChainDepthiterations (for now defined to be 100 in dynamic config).A lot of boilerplate from making a new API (proto + mock generated lines). Business logic to note are in:
service/frontend/workflow_handler.goservice/history/handler.goInvoke(...)implementation:service/history/api/getworkflowexecutionresult/api.goWhy?
Allows Nexus handler to map to this operation more ergonomically for callers.
How did you test it?
Potential risks
New API -- need more test across repos (load testing, etc...). Gated behind dynamic config.