-
Notifications
You must be signed in to change notification settings - Fork 1.8k
[SDK Ergonomics] NEXUS-519: Support Query-backed Nexus Operations #11274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,13 +5,14 @@ import ( | |
|
|
||
| "github.com/nexus-rpc/sdk-go/nexus" | ||
| commonpb "go.temporal.io/api/common/v1" | ||
| "go.temporal.io/api/temporalnexus" | ||
| "go.temporal.io/server/common/log" | ||
| "go.temporal.io/server/common/log/tag" | ||
| ) | ||
|
|
||
| // ConvertNexusLinksToProtoLinks converts a slice of Nexus SDK links into Temporal proto links, | ||
| // supporting Link_WorkflowEvent and Link_Activity variants. Unsupported or malformed entries | ||
| // are skipped with a warning since links are non-essential to execution. | ||
| // supporting Link_Workflow, Link_WorkflowEvent, and Link_Activity variants. Unsupported or | ||
| // malformed entries are skipped with a warning since links are non-essential to execution. | ||
| func ConvertNexusLinksToProtoLinks(nexusLinks []nexus.Link, logger log.Logger) []*commonpb.Link { | ||
| var out []*commonpb.Link | ||
| for _, nexusLink := range nexusLinks { | ||
|
|
@@ -40,6 +41,18 @@ func ConvertNexusLinksToProtoLinks(nexusLinks []nexus.Link, logger log.Logger) [ | |
| out = append(out, &commonpb.Link{ | ||
| Variant: &commonpb.Link_Activity_{Activity: link}, | ||
| }) | ||
| case string((&commonpb.Link_Workflow{}).ProtoReflect().Descriptor().FullName()): | ||
|
mavemuri marked this conversation as resolved.
|
||
| link, err := temporalnexus.ConvertNexusLinkToLinkWorkflow(nexusLink) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The two sibling cases use this repo's own converters (
Adding a local
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rejected
mavemuri marked this conversation as resolved.
mavemuri marked this conversation as resolved.
|
||
| if err != nil { | ||
| logger.Warn( | ||
| fmt.Sprintf("failed to parse link to %q: %s", nexusLink.Type, nexusLink.URL), | ||
| tag.Error(err), | ||
| ) | ||
| continue | ||
| } | ||
| out = append(out, &commonpb.Link{ | ||
| Variant: &commonpb.Link_Workflow_{Workflow: link}, | ||
| }) | ||
|
mavemuri marked this conversation as resolved.
|
||
| default: | ||
| logger.Warn(fmt.Sprintf("invalid link data type: %q", nexusLink.Type)) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,7 +37,7 @@ func Invoke( | |
| workflowConsistencyChecker api.WorkflowConsistencyChecker, | ||
| rawMatchingClient matchingservice.MatchingServiceClient, | ||
| matchingClient matchingservice.MatchingServiceClient, | ||
| ) (_ *historyservice.QueryWorkflowResponse, retError error) { | ||
| ) (resp *historyservice.QueryWorkflowResponse, retError error) { | ||
| scope := shardContext.GetMetricsHandler().WithTags(metrics.OperationTag(metrics.HistoryQueryWorkflowScope)) | ||
| namespaceID := namespace.ID(request.GetNamespaceId()) | ||
| err := api.ValidateNamespaceUUID(namespaceID) | ||
|
|
@@ -79,6 +79,27 @@ func Invoke( | |
| // Note: QueryWorkflow should not alter mutable state, so it is safe to ignore error and not clear ms. | ||
| workflowLease.GetReleaseFn()(nil) | ||
| }() | ||
| defer func() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That makes the link this PR returns a dead end for the main thing links are for: taking a link you got back and attaching it to a follow-up request. A client that does qResp, _ := c.WorkflowService().QueryWorkflow(ctx, ...)
c.WorkflowService().StartWorkflowExecution(ctx, &workflowservice.StartWorkflowExecutionRequest{
..., Links: []*commonpb.Link{qResp.GetLink()},
})gets Strictly this gap predates the PR — case *commonpb.Link_Workflow_:
if t.Workflow.GetNamespace() == "" {
return serviceerror.NewInvalidArgument("workflow link must not have an empty namespace field")
}
if t.Workflow.GetWorkflowId() == "" {
return serviceerror.NewInvalidArgument("workflow link must not have an empty workflow ID field")
}
if t.Workflow.GetRunId() == "" {
return serviceerror.NewInvalidArgument("workflow link must not have an empty run ID field")
} |
||
| if retError != nil || resp.GetResponse() == nil { | ||
| return | ||
| } | ||
| // Add link to Workflow regardless of query status. A rejection on the query is not an RPC error, | ||
| // so it gets the same link that a processed query would get - only the reason differs. | ||
|
mavemuri marked this conversation as resolved.
mavemuri marked this conversation as resolved.
mavemuri marked this conversation as resolved.
|
||
| reason := "Query processed" | ||
| if resp.GetResponse().GetQueryRejected() != nil { | ||
| reason = "Query rejected" | ||
| } | ||
| resp.Response.Link = &commonpb.Link{ | ||
|
mavemuri marked this conversation as resolved.
|
||
| Variant: &commonpb.Link_Workflow_{ | ||
| Workflow: &commonpb.Link_Workflow{ | ||
| Namespace: nsEntry.Name().String(), | ||
| WorkflowId: workflowKey.WorkflowID, | ||
| RunId: workflowKey.RunID, | ||
| Reason: reason, | ||
| }, | ||
| }, | ||
| } | ||
| }() | ||
|
mavemuri marked this conversation as resolved.
|
||
|
|
||
| // Context metadata is automatically set during mutable state transaction close for operations that mutate state. | ||
| // Since QueryWorkflow is readonly and never closes the transaction, we explicitly call SetContextMetadata | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.