Skip to content

Commit c61fa19

Browse files
Improve SANO sample (#507)
Improve SANO sample
1 parent 8418faf commit c61fa19

4 files changed

Lines changed: 66 additions & 40 deletions

File tree

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,50 @@
11
This sample demonstrates how to use Standalone Nexus Operations (executing Nexus operations directly from client code without wrapping them in a Workflow).
22
It shows both sync and async (workflow-backed) operations, and how to use the `ListNexusOperations` and `CountNexusOperations` APIs.
33

4-
## Note: Standalone Nexus operations require a server version that supports this feature. Use the dev server build at https://github.com/temporalio/cli/releases/tag/v1.7.3-standalone-nexus-operations.
4+
The starter and worker connect to two different namespaces (a "caller" namespace and a "handler" namespace) — this mirrors how Nexus is typically used to cross namespace boundaries. The client is configured via the SDK's [environment configuration](https://docs.temporal.io/develop/environment-configuration) support, which reads `TEMPORAL_NAMESPACE`, `TEMPORAL_ADDRESS`, etc. from the environment (and optionally profiles from `temporal.toml`).
55

6-
### Steps to run this sample (with expected output):
7-
1) Run the [Temporal dev server build that supports standalone Nexus operations](https://github.com/temporalio/cli/releases/tag/v1.7.3-standalone-nexus-operations). (If you are going to run locally, you will want to start it in another terminal; this command is blocking and runs until it receives a SIGINT (Ctrl + C) command.)
6+
## Note: Standalone Nexus operations require a server version that supports this feature. Use the dev server build at https://github.com/temporalio/cli/releases/tag/v1.7.4-standalone-nexus-operations.
87

9-
Start the dev server with the dynamic config flags required for standalone Nexus operations:
8+
## Run locally against a dev server
9+
10+
1) Start the [Temporal dev server build that supports standalone Nexus operations](https://docs.temporal.io/standalone-nexus-operation#temporal-cli-support) with the required namespaces pre-created:
1011

1112
```bash
12-
temporal server start-dev \
13-
--dynamic-config-value "nexusoperation.enableStandalone=true" \
14-
--dynamic-config-value "history.enableChasmCallbacks=true"
13+
./temporal server start-dev \
14+
--namespace my-caller-namespace \
15+
--namespace my-handler-namespace
1516
```
1617

17-
You should see a line about the CLI, Server and UI versions, and one line each for the Server URL, UI URL and Metrics endpoint. It should look something like this:
18+
2) Create a Nexus endpoint that routes to the handler namespace and the worker's task queue:
1819

1920
```bash
20-
Temporal CLI 1.7.3-standalone-nexus-operations (Server 1.32.0-158.0, UI 2.52.0)
21-
22-
Temporal Server: localhost:7233
23-
Temporal UI: http://localhost:8233
24-
Temporal Metrics: http://localhost:61951/metrics
21+
./temporal operator nexus endpoint create \
22+
--name my-nexus-endpoint \
23+
--target-namespace my-handler-namespace \
24+
--target-task-queue nexus-handler-queue
2525
```
2626

27-
2) Create a Nexus endpoint that routes to the worker's task queue. In a second terminal, run:
28-
```bash
29-
temporal operator nexus endpoint create \
30-
--name nexus-standalone-operations-endpoint \
31-
--target-namespace default \
32-
--target-task-queue nexus-standalone-operations
33-
```
27+
3) In a new terminal, start the worker in the handler namespace:
3428

35-
1) Then run the following command to start the worker. The worker is a blocking process that runs until it receives a SIGINT (Ctrl + C) command.
3629
```bash
37-
go run nexus-standalone-operations/worker/main.go
30+
TEMPORAL_NAMESPACE=my-handler-namespace \
31+
go run nexus-standalone-operations/worker/main.go
3832
```
3933

40-
You should see the following log line:
41-
1. Starting the Worker with Namespace `default`, and TaskQueue `nexus-standalone-operations` and it will list the WorkerID for the created worker.
34+
You should see a log line similar to:
4235

43-
For example:
4436
```bash
45-
2026/05/21 08:59:49 INFO Started Worker Namespace default TaskQueue nexus-standalone-operations WorkerID 71172
37+
2026/05/21 08:59:49 INFO Started Worker Namespace my-handler-namespace TaskQueue nexus-handler-queue WorkerID 71172
4638
```
4739

48-
> [!NOTE]
49-
> Timestamps and IDs will differ on your machine.
40+
4) In a third terminal, run the starter in the caller namespace:
5041

51-
4) In a third terminal, run the following command to start the example:
5242
```bash
53-
go run nexus-standalone-operations/starter/main.go
43+
TEMPORAL_NAMESPACE=my-caller-namespace \
44+
go run nexus-standalone-operations/starter/main.go
5445
```
5546

56-
You should see something similar to the following output:
47+
You should see something similar to:
5748

5849
```bash
5950
2026/05/21 09:00:30 Started Echo operation OperationID nexus-standalone-echo-op
@@ -66,5 +57,44 @@ You should see something similar to the following output:
6657
2026/05/21 09:00:30 Total Nexus operations: 2
6758
```
6859

69-
If you run the starter code multiple times, you should see additional `ListNexusOperations` results, as more operations are run.
70-
The same goes for the number from `CountNexusOperations`.
60+
If you run the starter multiple times, additional entries will appear in the `ListNexusOperations` output and the `CountNexusOperations` total will grow.
61+
62+
## Run against Temporal Cloud
63+
64+
1) Create two namespaces in Temporal Cloud (for example `my-caller-namespace.<account>` and `my-handler-namespace.<account>`) and generate an API key (or mTLS cert) that can access both.
65+
66+
2) Create a Nexus endpoint that targets the handler namespace and the worker's task queue. See the Temporal Cloud instructions at https://docs.temporal.io/nexus/registry#create-a-nexus-endpoint. Use:
67+
- Endpoint name: `my-nexus-endpoint`
68+
- Target namespace: `my-handler-namespace.<account>`
69+
- Target task queue: `nexus-handler-queue`
70+
- Allowed caller namespaces: include `my-caller-namespace.<account>` (endpoints reject callers that are not on this list)
71+
72+
3) Add two profiles to your [environment configuration file](https://docs.temporal.io/develop/environment-configuration), one per namespace. Using API keys:
73+
74+
```toml
75+
[profile.handler]
76+
address = "<region>.<cloud>.api.temporal.io:7233"
77+
namespace = "my-handler-namespace.<account>"
78+
api_key = "<your-api-key>"
79+
80+
[profile.caller]
81+
address = "<region>.<cloud>.api.temporal.io:7233"
82+
namespace = "my-caller-namespace.<account>"
83+
api_key = "<your-api-key>"
84+
```
85+
86+
For mTLS instead of API keys, set `tls.client_cert_path` and `tls.client_key_path` on each profile (see the [docs](https://docs.temporal.io/develop/environment-configuration) for the full schema).
87+
88+
4) Run the worker and starter in separate terminals, selecting the appropriate profile in each:
89+
90+
```bash
91+
# terminal 1 (worker, handler namespace)
92+
export TEMPORAL_PROFILE="handler"
93+
go run nexus-standalone-operations/worker/main.go
94+
```
95+
96+
```bash
97+
# terminal 2 (starter, caller namespace)
98+
export TEMPORAL_PROFILE="caller"
99+
go run nexus-standalone-operations/starter/main.go
100+
```

nexus-standalone-operations/handler_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,7 @@ func Test_StandaloneNexusOperations_Using_DevServer(t *testing.T) {
3333
// Start the dev server with standalone Nexus support.
3434
server, err := testsuite.StartDevServer(ctx, testsuite.DevServerOptions{
3535
CachedDownload: testsuite.CachedDownload{
36-
Version: "v1.7.3-standalone-nexus-operations",
37-
},
38-
ExtraArgs: []string{
39-
"--dynamic-config-value", "nexusoperation.enableStandalone=true",
40-
"--dynamic-config-value", "history.enableChasmCallbacks=true",
36+
Version: "v1.7.4-standalone-nexus-operations",
4137
},
4238
})
4339
require.NoError(t, err)

nexus-standalone-operations/starter/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
// This sample demonstrates standalone Nexus operations — executing Nexus operations
1717
// directly from client code without wrapping them in a workflow.
1818

19-
const endpointName = "nexus-standalone-operations-endpoint"
19+
const endpointName = "my-nexus-endpoint"
2020

2121
func main() {
2222
// The client is a heavyweight object that should be created once per process.

nexus-standalone-operations/worker/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"github.com/temporalio/samples-go/nexus/service"
1515
)
1616

17-
const taskQueue = "nexus-standalone-operations"
17+
const taskQueue = "nexus-handler-queue"
1818

1919
func main() {
2020
// The client and worker are heavyweight objects that should be created once per process.

0 commit comments

Comments
 (0)