Skip to content

Nexus Standalone: Terminate + Cancel#9624

Open
stephanos wants to merge 20 commits intofeature/nexus-standalonefrom
stephanos/nexus-standalone-cancel
Open

Nexus Standalone: Terminate + Cancel#9624
stephanos wants to merge 20 commits intofeature/nexus-standalonefrom
stephanos/nexus-standalone-cancel

Conversation

@stephanos
Copy link
Contributor

@stephanos stephanos commented Mar 23, 2026

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

Can't verify functional tests yet due to missing impl.

@stephanos stephanos changed the base branch from main to feature/nexus-standalone March 23, 2026 15:14
@stephanos stephanos changed the title Stephanos/nexus standalone cancel Nexus Standalone: Terminate + Cancel Mar 23, 2026
@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch 4 times, most recently from a69b3a4 to 3bc48be Compare March 23, 2026 21:16
len(req.GetIdentity()), config.MaxIDLengthLimit())
}
return nil
}
Copy link
Contributor Author

@stephanos stephanos Mar 23, 2026

Choose a reason for hiding this comment

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

^ I considered re-using these by introducing an interface or two, but then again ... maybe that's overkill.

Copy link
Member

Choose a reason for hiding this comment

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

Overkill IMHO

@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch 10 times, most recently from 5a99e83 to c7313a0 Compare March 24, 2026 01:18
s.Contains(err.Error(), "operation_id is required")
})
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

^ will need to verify and maybe tweak tests once everything's implemented

@stephanos stephanos marked this pull request as ready for review March 24, 2026 01:19
@stephanos stephanos requested review from a team as code owners March 24, 2026 01:19
@stephanos stephanos requested review from bergundy and gow March 24, 2026 01:19
@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch from c7313a0 to d1b9216 Compare March 24, 2026 01:25
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.

The only thing that's missing for me is request ID dedupe.

})

resp, _, err := chasm.UpdateComponent(ctx, ref, func(o *Operation, ctx chasm.MutableContext, req *nexusoperationpb.TerminateNexusOperationRequest) (*nexusoperationpb.TerminateNexusOperationResponse, error) {
_, err := o.Terminate(ctx, chasm.TerminateComponentRequest{
Copy link
Member

Choose a reason for hiding this comment

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

Missing a request ID here (not sure if this is already in the API but it should be.

})

resp, _, err := chasm.UpdateComponent(ctx, ref, func(o *Operation, ctx chasm.MutableContext, req *nexusoperationpb.RequestCancelNexusOperationRequest) (*nexusoperationpb.RequestCancelNexusOperationResponse, error) {
if err := o.Cancel(ctx, nil); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Let's dedupe here based on a cancel request ID. See SAA for reference.

len(req.GetIdentity()), config.MaxIDLengthLimit())
}
return nil
}
Copy link
Member

Choose a reason for hiding this comment

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

Overkill IMHO

Comment on lines +160 to +196
func validateRequestCancelNexusOperationExecutionRequest(req *workflowservice.RequestCancelNexusOperationExecutionRequest, config *Config) error {
if req.GetOperationId() == "" {
return serviceerror.NewInvalidArgument("operation_id is required")
}
if len(req.GetOperationId()) > config.MaxIDLengthLimit() {
return serviceerror.NewInvalidArgumentf("operation_id exceeds length limit. Length=%d Limit=%d",
len(req.GetOperationId()), config.MaxIDLengthLimit())
}
if len(req.GetRunId()) > config.MaxIDLengthLimit() {
return serviceerror.NewInvalidArgumentf("run_id exceeds length limit. Length=%d Limit=%d",
len(req.GetRunId()), config.MaxIDLengthLimit())
}
if len(req.GetIdentity()) > config.MaxIDLengthLimit() {
return serviceerror.NewInvalidArgumentf("identity exceeds length limit. Length=%d Limit=%d",
len(req.GetIdentity()), config.MaxIDLengthLimit())
}
return nil
}

func validateTerminateNexusOperationExecutionRequest(req *workflowservice.TerminateNexusOperationExecutionRequest, config *Config) error {
if req.GetOperationId() == "" {
return serviceerror.NewInvalidArgument("operation_id is required")
}
if len(req.GetOperationId()) > config.MaxIDLengthLimit() {
return serviceerror.NewInvalidArgumentf("operation_id exceeds length limit. Length=%d Limit=%d",
len(req.GetOperationId()), config.MaxIDLengthLimit())
}
if len(req.GetRunId()) > config.MaxIDLengthLimit() {
return serviceerror.NewInvalidArgumentf("run_id exceeds length limit. Length=%d Limit=%d",
len(req.GetRunId()), config.MaxIDLengthLimit())
}
if len(req.GetIdentity()) > config.MaxIDLengthLimit() {
return serviceerror.NewInvalidArgumentf("identity exceeds length limit. Length=%d Limit=%d",
len(req.GetIdentity()), config.MaxIDLengthLimit())
}
return nil
}
Copy link
Member

Choose a reason for hiding this comment

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

We need a request ID on both of these and to validate it

@stephanos stephanos requested a review from a team as a code owner March 24, 2026 21:00
@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch from f8c16bc to 49cb758 Compare March 24, 2026 21:11
@stephanos stephanos requested a review from a team as a code owner March 24, 2026 21:11
@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch 4 times, most recently from 1b50884 to c4dcd26 Compare March 24, 2026 21:40
@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch from c4dcd26 to db6cfb6 Compare March 24, 2026 21:41

// The reason for requesting cancellation.
string reason = 10;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

^ mimicking ActivityCancelState

@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch from bbd18bd to 47463a8 Compare March 24, 2026 22:51
@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch from 47463a8 to 9639961 Compare March 24, 2026 23:02
len(req.GetIdentity()), config.MaxIDLengthLimit())
}

// TODO: use different config for limit
Copy link
Contributor Author

Choose a reason for hiding this comment

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

As the comment says, I'll leave this here for now (mimics SAA) but we're investigating a better option

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was failing tests after rebase

@stephanos stephanos requested a review from bergundy March 25, 2026 00:12
}

message NexusOperationTerminateState {
string request_id = 1;
Copy link
Member

Choose a reason for hiding this comment

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

Please add a comment explaining what this is and how it is used.

}

if req.GetRequestId() == "" {
// Since this mutates the request, we clone it first so that any retries use the original request.
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't seem necessary and would be preferable if we used the same request ID for retries.

Copy link
Member

Choose a reason for hiding this comment

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

Also, can you say when this request would ever be retried from this location? I think I'm missing something.

Copy link
Contributor Author

@stephanos stephanos Mar 25, 2026

Choose a reason for hiding this comment

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

Right; this is verbatim from SAA (I assumed what's there was reviewed and is a blessed pattern). I hadn't seen it before either ... 👀

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tracked this down and I believe this was an overcorrection on the SAA team; I've let them know.

}))
}

func (o *Operation) handleCancellationRequested(
Copy link
Member

Choose a reason for hiding this comment

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

Should this be called requestCancel for consistency with Terminate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also followed the SAA naming here; but I also like requestCancel 👍


return chasm.TerminateComponentResponse{}, nil
}

Copy link
Member

Choose a reason for hiding this comment

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

There's nothing transitioning to the terminated state here... You should also store the terminate reason somehow. I would look at SAA to figure out the best place to store it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right; that's why I have "unimplemented" there. I was under the impression that isn't available yet; ie blocked on the HSM to CHASM migration. Let me take a closer look again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Talked offline; it's in scope here - added now.

return chasm.TerminateComponentResponse{}, nil
}

return chasm.TerminateComponentResponse{}, serviceerror.NewUnimplemented("not implemented")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return chasm.TerminateComponentResponse{}, serviceerror.NewUnimplemented("not implemented")
return chasm.TerminateComponentResponse{}, nil

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not quite as we'll need a transition - added now.

return o.handleCancellation(ctx, newCancellation(req))
}

func (o *Operation) handleCancellation(
Copy link
Member

Choose a reason for hiding this comment

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

Do we need this separate method?

Copy link
Contributor Author

@stephanos stephanos Mar 25, 2026

Choose a reason for hiding this comment

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

Yes, unless we should duplicate the code since it's called from both Cancel and requestCancel?

@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch from baa41d7 to 808f1f6 Compare March 25, 2026 20:57
} else if len(req.GetRequestId()) > config.MaxIDLengthLimit() {
return serviceerror.NewInvalidArgumentf("request_id exceeds length limit. Length=%d Limit=%d",
len(req.GetRequestId()), config.MaxIDLengthLimit())
}
Copy link
Contributor Author

@stephanos stephanos Mar 25, 2026

Choose a reason for hiding this comment

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

Moved them all here from frontend; and to the top for easier scanning.

// Request ID used to deduplicate terminate requests.
string request_id = 1;
// The identity of the client who requested termination.
string identity = 2;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need this to store the identity, too. Even though there's no way to query it for the user (yet?).

@stephanos stephanos force-pushed the stephanos/nexus-standalone-cancel branch from adf30e8 to 65847d9 Compare March 25, 2026 22:11
@stephanos stephanos requested a review from bergundy March 25, 2026 22:15
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.

2 participants