88 "testing"
99 "time"
1010
11+ "github.com/google/uuid"
1112 "github.com/nexus-rpc/sdk-go/nexus"
1213 "github.com/stretchr/testify/assert"
1314 "github.com/stretchr/testify/require"
@@ -19,6 +20,10 @@ import (
1920 "go.temporal.io/api/serviceerror"
2021 taskqueuepb "go.temporal.io/api/taskqueue/v1"
2122 "go.temporal.io/api/workflowservice/v1"
23+ "go.temporal.io/sdk/client"
24+ "go.temporal.io/sdk/temporalnexus"
25+ "go.temporal.io/sdk/worker"
26+ "go.temporal.io/sdk/workflow"
2227 persistencespb "go.temporal.io/server/api/persistence/v1"
2328 "go.temporal.io/server/chasm/lib/nexusoperation"
2429 "go.temporal.io/server/common/dynamicconfig"
@@ -2123,6 +2128,58 @@ func (s *NexusStandaloneTestSuite) TestStandaloneNexusOperationPoll() {
21232128 })
21242129}
21252130
2131+ // TestAsyncCompletionAgainstWorkflowHandler exercises the full end-to-end completion path
2132+ // for a standalone (CHASM) Nexus operation whose handler is an SDK workflow registered via
2133+ // temporalnexus.NewWorkflowRunOperation against a Worker-target endpoint. With
2134+ // EnableCHASMCallbacks defaulted to false, the handler workflow's completion is delivered
2135+ // through the legacy HSM callback machine, so this test covers the cross-stack combination
2136+ // that previously failed with `NamespaceID is empty.` before the callback token began
2137+ // dual-populating HSM-shaped routing fields.
2138+ func (s * NexusStandaloneTestSuite ) TestAsyncCompletionAgainstWorkflowHandler () {
2139+ env := s .newTestEnv ()
2140+ ctx := env .Context ()
2141+
2142+ handlerTaskQueue := testcore .RandomizeStr (s .T ().Name ())
2143+ endpointName := env .createNexusEndpoint (ctx , s .T (), testcore .RandomizedNexusEndpoint (s .T ().Name ()), handlerTaskQueue ).GetSpec ().GetName ()
2144+
2145+ handlerWF := func (workflow.Context , nexus.NoValue ) (string , error ) {
2146+ return "ok" , nil
2147+ }
2148+
2149+ svc := nexus .NewService ("test-service" )
2150+ nexusOp := temporalnexus .NewWorkflowRunOperation ("test-operation" , handlerWF ,
2151+ func (_ context.Context , _ nexus.NoValue , _ nexus.StartOperationOptions ) (client.StartWorkflowOptions , error ) {
2152+ return client.StartWorkflowOptions {
2153+ ID : "handler-wf-" + uuid .NewString (),
2154+ TaskQueue : handlerTaskQueue ,
2155+ }, nil
2156+ })
2157+ svc .MustRegister (nexusOp )
2158+
2159+ w := worker .New (env .SdkClient (), handlerTaskQueue , worker.Options {})
2160+ w .RegisterWorkflow (handlerWF )
2161+ w .RegisterNexusService (svc )
2162+ s .NoError (w .Start ())
2163+ defer w .Stop ()
2164+
2165+ startResp , err := s .startNexusOperation (env , & workflowservice.StartNexusOperationExecutionRequest {
2166+ OperationId : "test-op" ,
2167+ Endpoint : endpointName ,
2168+ })
2169+ s .NoError (err )
2170+
2171+ s .EventuallyWithT (func (t * assert.CollectT ) {
2172+ descResp , err := env .FrontendClient ().DescribeNexusOperationExecution (ctx , & workflowservice.DescribeNexusOperationExecutionRequest {
2173+ Namespace : env .Namespace ().String (),
2174+ OperationId : "test-op" ,
2175+ RunId : startResp .RunId ,
2176+ IncludeOutcome : true ,
2177+ })
2178+ require .NoError (t , err )
2179+ require .Equal (t , enumspb .NEXUS_OPERATION_EXECUTION_STATUS_COMPLETED , descResp .GetInfo ().GetStatus ())
2180+ }, 30 * time .Second , 200 * time .Millisecond )
2181+ }
2182+
21262183func (s * NexusStandaloneTestSuite ) TestAsyncCompletionIgnoresTransitionFieldsInCallbackToken () {
21272184 env := s .newTestEnv ()
21282185 handlerLink := & commonpb.Link_WorkflowEvent {
0 commit comments