Skip to content
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

Set Nexus operation ID on callback headers #1710

Merged
merged 14 commits into from
Nov 27, 2024
Merged

Conversation

pdoerner
Copy link
Contributor

@pdoerner pdoerner commented Nov 15, 2024

What was changed

Setting nexus-operation-id header on callback headers.
Depends on nexus-rpc/sdk-go#26
Returns an error is the workflow ID is unset on the start options for a Nexus operation

Why?

This information is necessary for fabricating a NexusOperationStarted event if the completion is received before the response to a StartOperation request. This ID is set to the workflow ID unless the user provides a value for this header; user-provided values for this header are not overwritten.

Checklist

  1. Closes

  2. How was this tested:

Existing tests

  1. Any docs updates needed?

Copy link
Member

@bergundy bergundy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Another non-blocking request is to always have the server generate the links (SDK can generate as a fallback when used with an old server).
That way operation ID is always coming from the SDK and the link from the server.

We should also document the implications of changing the operation ID returned from WorkflowRunOperation.Start. Let's tell them to never do that because the ID is used for cancelation and is reporting completion from the server.

@@ -324,12 +325,21 @@ func ExecuteUntypedWorkflow[R any](
if startWorkflowOptions.TaskQueue == "" {
startWorkflowOptions.TaskQueue = nctx.TaskQueue
}
if startWorkflowOptions.ID == "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we want to require setting workflow ID for Nexus operations. We require it in all Core based SDKs, maybe we can at least protect Nexus users. Not blocking this PR though. @cretz, @Quinn-With-Two-Ns to weigh in on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the Go SDK did require setting a workflow ID for Nexus operations? I think it makes sense to require it or at least default it to something deterministic so starting a workflow is idempotent

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this was my intent but I think the client will automatically fill in an ID unless one is provided. Need to verify this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We require it meaning I don't need the check for it being empty here? I looked for where a default would be set but didn't find anything that would set it before this point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change to ensure that the client doesn't auto generate an ID if one isn't set.

We should note this change in the release notes. I would consider it a backwards incompatible behavior change.

	if startWorkflowOptions.ID == "" {
		return nil, ErrMissingWorkflowID
	}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdoerner this already changed for Java, please make sure to disallow empty workflow ID for nexus ops before merging this.

@pdoerner
Copy link
Contributor Author

@bergundy re this comment

Another non-blocking request is to always have the server generate the links (SDK can generate as a fallback when used with an old server). That way operation ID is always coming from the SDK and the link from the server.

I didn't add any generation for links here; are you suggesting I should add the fallback?

Copy link
Member

@bergundy bergundy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change the behavior when there's a missing workflow ID.

@bergundy
Copy link
Member

@bergundy re this comment

Another non-blocking request is to always have the server generate the links (SDK can generate as a fallback when used with an old server). That way operation ID is always coming from the SDK and the link from the server.

I didn't add any generation for links here; are you suggesting I should add the fallback?

I'm saying we modify the server to return links and only generate them in the SDK in if the server doesn't return them in the StartWorkflowExecutionResponse. We'll need to consider when to return these links though. I opened an issue to track this, it's not blocking.

@@ -338,6 +338,9 @@ var (

// ErrSkipScheduleUpdate is used by a user if they want to skip updating a schedule.
ErrSkipScheduleUpdate = errors.New("skip schedule update")

// ErrMissingWorkflowID is returned when trying to start an async Nexus operation but no workflow ID is set on the request.
ErrMissingWorkflowID = errors.New("workflow ID is unset")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit can the error message make it clear that it was unset for a Nexus operation

@pdoerner pdoerner marked this pull request as ready for review November 27, 2024 17:39
@pdoerner pdoerner requested a review from a team as a code owner November 27, 2024 17:39
if nexusOptions.CallbackHeader == nil {
nexusOptions.CallbackHeader = make(nexus.Header)
}
if _, set := nexusOptions.CallbackHeader[nexus.HeaderOperationID]; !set {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should we use the case insensitive operations on the headers? I guess nexus.HeaderOperationID is now lower case so it isn't that important.

@pdoerner pdoerner merged commit 520b525 into master Nov 27, 2024
14 checks passed
@pdoerner pdoerner deleted the nexus-complete-before-start branch November 27, 2024 20:13
pdoerner added a commit to temporalio/temporal that referenced this pull request Nov 27, 2024
## What changed?
<!-- Describe what has changed in this PR -->
Added support for completing Nexus operations before the StartOperation
response is received. Operation ID, StartTime, and StartLinks were added
to the completion request so that a NexusOperationStarted event can be
fabricated.
Depends on nexus-rpc/sdk-go#26 and
temporalio/sdk-go#1710

Bumps Temporal SDK version to `v1.30.1`
Bumps Nexus SDK version to `v0.0.12`

## Why?
<!-- Tell your future self why have you made these changes -->
Better user experience.

## How did you test it?
<!-- How have you verified this change? Tested locally? Added a unit
test? Checked in staging env? -->
New functional test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants