Skip to content

Commit 2c57d96

Browse files
committed
Changes from reviewing
1 parent db374ea commit 2c57d96

16 files changed

Lines changed: 182 additions & 152 deletions

src/NexusMessaging/Callerpattern/Caller/CallerWorkflow.workflow.cs renamed to src/NexusMessaging/CallerPattern/Caller/CallerWorkflow.workflow.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
namespace TemporalioSamples.NexusMessaging.Callerpattern.Caller;
1+
namespace TemporalioSamples.NexusMessaging.CallerPattern.Caller;
22

33
using Temporalio.Workflows;
4-
using TemporalioSamples.NexusMessaging.Callerpattern;
4+
using TemporalioSamples.NexusMessaging.CallerPattern;
55
using TemporalioSamples.NexusMessaging.Common;
66

77
[Workflow]

src/NexusMessaging/Callerpattern/Handler/GreetingWorkflow.workflow.cs renamed to src/NexusMessaging/CallerPattern/Handler/GreetingWorkflow.workflow.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
namespace TemporalioSamples.NexusMessaging.Callerpattern.Handler;
1+
namespace TemporalioSamples.NexusMessaging.CallerPattern.Handler;
22

33
using Temporalio.Exceptions;
44
using Temporalio.Workflows;
5-
using TemporalioSamples.NexusMessaging.Callerpattern;
5+
using TemporalioSamples.NexusMessaging.CallerPattern;
66
using TemporalioSamples.NexusMessaging.Common;
77

88
[Workflow]

src/NexusMessaging/Callerpattern/Handler/NexusGreetingService.cs renamed to src/NexusMessaging/CallerPattern/Handler/NexusGreetingService.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
1-
namespace TemporalioSamples.NexusMessaging.Callerpattern.Handler;
1+
namespace TemporalioSamples.NexusMessaging.CallerPattern.Handler;
22

33
using NexusRpc.Handlers;
44
using Temporalio.Nexus;
5-
using TemporalioSamples.NexusMessaging.Callerpattern;
5+
using TemporalioSamples.NexusMessaging.CallerPattern;
66
using TemporalioSamples.NexusMessaging.Common;
77

8+
// Entity pattern: the handler worker pre-starts a GreetingWorkflow per user at boot time.
9+
// This service routes each Nexus operation to that existing workflow by deriving the
10+
// workflow ID from the caller-supplied UserId.
811
[NexusServiceHandler(typeof(INexusGreetingService))]
912
public class NexusGreetingService
1013
{
14+
// OperationHandler.Sync means the result is returned inline to the Nexus caller
15+
// (as opposed to WorkflowRunOperationHandler, which returns an async operation token).
16+
// The lambda may still be async internally.
17+
18+
// Query: read-only, no state mutation — uses workflow query
1119
[NexusOperationHandler]
1220
public IOperationHandler<INexusGreetingService.GetLanguagesInput, INexusGreetingService.GetLanguagesOutput> GetLanguages() =>
1321
OperationHandler.Sync<INexusGreetingService.GetLanguagesInput, INexusGreetingService.GetLanguagesOutput>(
1422
async (ctx, input) =>
1523
{
24+
// Access the Temporal client from the Nexus operation context
1625
var client = NexusOperationExecutionContext.Current.TemporalClient;
1726
var handle = client.GetWorkflowHandle<GreetingWorkflow>(WorkflowIdForUser(input.UserId));
1827
return await handle.QueryAsync(wf => wf.QueryLanguages(input.IncludeUnsupported));
1928
});
2029

30+
// Query: read-only — returns the workflow's current language
2131
[NexusOperationHandler]
2232
public IOperationHandler<INexusGreetingService.GetLanguageInput, Language> GetLanguage() =>
2333
OperationHandler.Sync<INexusGreetingService.GetLanguageInput, Language>(
@@ -28,6 +38,7 @@ public class NexusGreetingService
2838
return await handle.QueryAsync(wf => wf.QueryLanguage());
2939
});
3040

41+
// Update: mutates state and returns the previous value — uses workflow update
3142
[NexusOperationHandler]
3243
public IOperationHandler<INexusGreetingService.SetLanguageInput, Language> SetLanguage() =>
3344
OperationHandler.Sync<INexusGreetingService.SetLanguageInput, Language>(
@@ -38,6 +49,7 @@ public class NexusGreetingService
3849
return await handle.ExecuteUpdateAsync(wf => wf.SetLanguageAsync(input.Language));
3950
});
4051

52+
// Signal: fire-and-forget, no return value needed — uses workflow signal
4153
[NexusOperationHandler]
4254
public IOperationHandler<INexusGreetingService.ApproveInput, NoValue> Approve() =>
4355
OperationHandler.Sync<INexusGreetingService.ApproveInput, NoValue>(

src/NexusMessaging/Callerpattern/INexusGreetingService.cs renamed to src/NexusMessaging/CallerPattern/INexusGreetingService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
namespace TemporalioSamples.NexusMessaging.Callerpattern;
1+
namespace TemporalioSamples.NexusMessaging.CallerPattern;
22

33
using NexusRpc;
44
using TemporalioSamples.NexusMessaging.Common;
55

66
[NexusService]
77
public interface INexusGreetingService
88
{
9-
public static readonly string EndpointName = "nexus-messaging-nexus-endpoint";
9+
static readonly string EndpointName = "nexus-messaging-nexus-endpoint";
1010

1111
[NexusOperation]
1212
GetLanguagesOutput GetLanguages(GetLanguagesInput input);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## Entity pattern
2+
3+
The handler worker starts a `GreetingWorkflow` for a user ID at boot time.
4+
`NexusGreetingService` routes every Nexus operation to that existing workflow by deriving
5+
the workflow ID from the caller-supplied `UserId` (see the `WorkflowIdForUser` call).
6+
The caller passes a `UserId`, not a workflow ID -- the handler is responsible for the
7+
ID mapping.
8+
9+
The caller workflow:
10+
1. Queries for supported languages (`GetLanguages` -- backed by a workflow query)
11+
2. Queries the current language (`GetLanguage` -- backed by a workflow query)
12+
3. Changes the language to Chinese (`SetLanguage` -- backed by a workflow update that calls an activity)
13+
4. Approves the workflow (`Approve` -- backed by a workflow signal)
14+
15+
### Running
16+
17+
Start a Temporal server:
18+
19+
```bash
20+
temporal server start-dev
21+
```
22+
23+
Create the namespaces and Nexus endpoint:
24+
25+
```bash
26+
temporal operator namespace create --namespace nexus-messaging-handler-namespace
27+
temporal operator namespace create --namespace nexus-messaging-caller-namespace
28+
29+
temporal operator nexus endpoint create \
30+
--name nexus-messaging-nexus-endpoint \
31+
--target-namespace nexus-messaging-handler-namespace \
32+
--target-task-queue nexus-messaging-handler-sample
33+
```
34+
35+
In one terminal, start the handler worker:
36+
37+
```bash
38+
dotnet run --project src/NexusMessaging -- handler-worker
39+
```
40+
41+
In a second terminal, start the caller worker:
42+
43+
```bash
44+
dotnet run --project src/NexusMessaging -- caller-worker
45+
```
46+
47+
In a third terminal, start the caller workflow:
48+
49+
```bash
50+
dotnet run --project src/NexusMessaging -- caller-workflow
51+
```
File renamed without changes.

src/NexusMessaging/Ondemandpattern/Caller/CallerRemoteWorkflow.workflow.cs renamed to src/NexusMessaging/OnDemandPattern/Caller/CallerRemoteWorkflow.workflow.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
namespace TemporalioSamples.NexusMessaging.Ondemandpattern.Caller;
1+
namespace TemporalioSamples.NexusMessaging.OnDemandPattern.Caller;
22

33
using Temporalio.Workflows;
44
using TemporalioSamples.NexusMessaging.Common;
5-
using TemporalioSamples.NexusMessaging.Ondemandpattern;
5+
using TemporalioSamples.NexusMessaging.OnDemandPattern;
66

77
[Workflow]
88
public class CallerRemoteWorkflow

src/NexusMessaging/Ondemandpattern/Handler/GreetingWorkflow.workflow.cs renamed to src/NexusMessaging/OnDemandPattern/Handler/GreetingWorkflow.workflow.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
namespace TemporalioSamples.NexusMessaging.Ondemandpattern.Handler;
1+
namespace TemporalioSamples.NexusMessaging.OnDemandPattern.Handler;
22

33
using Temporalio.Exceptions;
44
using Temporalio.Workflows;
55
using TemporalioSamples.NexusMessaging.Common;
6-
using TemporalioSamples.NexusMessaging.Ondemandpattern;
6+
using TemporalioSamples.NexusMessaging.OnDemandPattern;
77

88
[Workflow]
99
public class GreetingWorkflow
@@ -19,7 +19,7 @@ public class GreetingWorkflow
1919
private string approvedBy = string.Empty;
2020

2121
[WorkflowRun]
22-
public async Task<string> RunAsync(string workflowId)
22+
public async Task<string> RunAsync(string userId)
2323
{
2424
// Wait for approve signal and all handlers to finish
2525
await Workflow.WaitConditionAsync(() => approved && Workflow.AllHandlersFinished);

src/NexusMessaging/Ondemandpattern/Handler/NexusRemoteGreetingService.cs renamed to src/NexusMessaging/OnDemandPattern/Handler/NexusRemoteGreetingService.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,44 @@
1-
namespace TemporalioSamples.NexusMessaging.Ondemandpattern.Handler;
1+
namespace TemporalioSamples.NexusMessaging.OnDemandPattern.Handler;
22

33
using NexusRpc.Handlers;
44
using Temporalio.Nexus;
55
using TemporalioSamples.NexusMessaging.Common;
6-
using TemporalioSamples.NexusMessaging.Ondemandpattern;
6+
using TemporalioSamples.NexusMessaging.OnDemandPattern;
77

8+
// On-demand pattern: no workflow is pre-started. The caller creates workflow instances
9+
// through Nexus operations. Each operation includes a UserId so the handler can derive
10+
// the target workflow ID.
811
[NexusServiceHandler(typeof(INexusRemoteGreetingService))]
912
public class NexusRemoteGreetingService
1013
{
14+
// WorkflowRunOperationHandler starts a backing workflow and returns its handle to the
15+
// Nexus infrastructure. The caller receives an async operation token and can poll for
16+
// the workflow result later via GetResultAsync.
1117
[NexusOperationHandler]
1218
public IOperationHandler<INexusRemoteGreetingService.RunFromRemoteInput, string> RunFromRemote() =>
1319
WorkflowRunOperationHandler.FromHandleFactory(
1420
(WorkflowRunOperationContext context, INexusRemoteGreetingService.RunFromRemoteInput input) =>
1521
context.StartWorkflowAsync(
16-
(GreetingWorkflow wf) => wf.RunAsync(GetWorkflowId(input.UserId)),
22+
(GreetingWorkflow wf) => wf.RunAsync(input.UserId),
1723
new() { Id = GetWorkflowId(input.UserId) }));
1824

25+
// OperationHandler.Sync means the result is returned inline to the Nexus caller
26+
// (as opposed to WorkflowRunOperationHandler, which returns an async operation token).
27+
// The lambda may still be async internally.
28+
29+
// Query: read-only, no state mutation — uses workflow query
1930
[NexusOperationHandler]
2031
public IOperationHandler<INexusRemoteGreetingService.GetLanguagesInput, INexusRemoteGreetingService.GetLanguagesOutput> GetLanguages() =>
2132
OperationHandler.Sync<INexusRemoteGreetingService.GetLanguagesInput, INexusRemoteGreetingService.GetLanguagesOutput>(
2233
async (ctx, input) =>
2334
{
35+
// Access the Temporal client from the Nexus operation context
2436
var client = NexusOperationExecutionContext.Current.TemporalClient;
2537
var handle = client.GetWorkflowHandle<GreetingWorkflow>(GetWorkflowId(input.UserId));
2638
return await handle.QueryAsync(wf => wf.QueryLanguages(input.IncludeUnsupported));
2739
});
2840

41+
// Query: read-only — returns the workflow's current language
2942
[NexusOperationHandler]
3043
public IOperationHandler<INexusRemoteGreetingService.GetLanguageInput, Language> GetLanguage() =>
3144
OperationHandler.Sync<INexusRemoteGreetingService.GetLanguageInput, Language>(
@@ -36,6 +49,7 @@ public class NexusRemoteGreetingService
3649
return await handle.QueryAsync(wf => wf.QueryLanguage());
3750
});
3851

52+
// Update: mutates state and returns the previous value — uses workflow update
3953
[NexusOperationHandler]
4054
public IOperationHandler<INexusRemoteGreetingService.SetLanguageInput, Language> SetLanguage() =>
4155
OperationHandler.Sync<INexusRemoteGreetingService.SetLanguageInput, Language>(
@@ -46,6 +60,7 @@ public class NexusRemoteGreetingService
4660
return await handle.ExecuteUpdateAsync(wf => wf.SetLanguageAsync(input.Language));
4761
});
4862

63+
// Signal: fire-and-forget, no return value needed — uses workflow signal
4964
[NexusOperationHandler]
5065
public IOperationHandler<INexusRemoteGreetingService.ApproveInput, NoValue> Approve() =>
5166
OperationHandler.Sync<INexusRemoteGreetingService.ApproveInput, NoValue>(

0 commit comments

Comments
 (0)