Skip to content

Commit da7202a

Browse files
authored
Nexus support (#517)
1 parent 45e61c8 commit da7202a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+3465
-74
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ jobs:
1515
include:
1616
- os: windows-latest
1717
checkTarget: true
18-
# We want to use one version for most things and this latest for
19-
# others. This is an ok way to test both without requiring a
20-
# separate matrix permutation.
21-
dotNetVersionOverride: 8.x
2218
- os: ubuntu-latest
2319
docsTarget: true
2420
cloudTestTarget: true

README.md

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Extensions:
4747
- [Running Workflows](#running-workflows)
4848
- [Invoking Activities](#invoking-activities)
4949
- [Invoking Child Workflows](#invoking-child-workflows)
50+
- [Invoking Nexus Operations](#invoking-nexus-operations)
5051
- [Timers and Conditions](#timers-and-conditions)
5152
- [Workflow Task Scheduling and Cancellation](#workflow-task-scheduling-and-cancellation)
5253
- [Workflow Utilities](#workflow-utilities)
@@ -66,6 +67,8 @@ Extensions:
6667
- [Activity Heartbeating and Cancellation](#activity-heartbeating-and-cancellation)
6768
- [Activity Worker Shutdown](#activity-worker-shutdown)
6869
- [Activity Testing](#activity-testing)
70+
- [Nexus](#nexus)
71+
- [Nexus Operations Backed by Workflows](#nexus-operations-backed-by-workflows)
6972
- [OpenTelemetry Tracing Support](#opentelemetry-tracing-support)
7073
- [Built-in Native Shared Library](#built-in-native-shared-library)
7174
- [TLS/CA Loading Issues](#tlsca-loading-issues)
@@ -325,7 +328,7 @@ var client = await TemporalClient.ConnectAsync(new()
325328

326329
### Workers
327330

328-
Workers host workflows and/or activities. Here's how to run a worker:
331+
Workers host workflows, activities, and Nexus services. Here's how to run a worker:
329332

330333
```csharp
331334
using MyNamespace;
@@ -570,7 +573,7 @@ Some things to note about the above code:
570573
* Child workflows are started with `Workflow.StartChildWorkflowAsync` which accepts a lambda expression whose parameter
571574
is the child workflow to call and the expression is a call to its run method with arguments.
572575
* A non-type-safe form of `StartChildWorkflowAsync` exists that just accepts a string workflow name.
573-
* Child workflow options are a simple class set after after the lambda expression or name.
576+
* Child workflow options are a simple class set after the lambda expression or name.
574577
* These options are optional.
575578
* Retry policy, ID, etc can also be set on the options.
576579
* Cancellation token is defaulted as the workflow cancellation token, but an alternative can be given in options.
@@ -582,6 +585,19 @@ Some things to note about the above code:
582585
* A shortcut of `Workflow.ExecuteChildWorkflowAsync` is available which is `StartChildWorkflowAsync` + `GetResultAsync`
583586
for those only needing to wait on its result.
584587

588+
#### Invoking Nexus Operations
589+
590+
* Nexus operations are started by first obtaining a Nexus client for a service via `Workflow.CreateNexusClient`, then
591+
invoking `StartNexusOperationAsync` on it which accepts a lambda expression for the call on the service.
592+
* Non-type-safe forms of `Workflow.CreateNexusClient` and `StartNexusOperationAsync` exist that just accept string
593+
service and operation names.
594+
* Nexus client and operation options are simple classes optionally provided as the last parameter.
595+
* Result of a Nexus operation starting is a `NexusOperationHandle` which has the operation token and `GetResultAsync`
596+
for getting the result.
597+
* The task for starting a Nexus operation does not complete until the operation has actually started.
598+
* A shortcut of `ExecuteNexusOperationAsync` is available which is `StartNexusOperationAsync` + `GetResultAsync` for
599+
those only needing to wait on its result.
600+
585601
#### Timers and Conditions
586602

587603
* A timer is represented by `Workflow.DelayAsync`.
@@ -1121,6 +1137,59 @@ activity context:
11211137
* `PayloadConverter` - Defaulted to default payload converter.
11221138
* `MetricMeter` - Defaulted to noop meter.
11231139

1140+
### Nexus
1141+
1142+
This covers Temporal-specific Nexus extensions. For general Nexus information/documentation, see
1143+
[the Nexus .NET SDK repository](https://github.com/nexus-rpc/sdk-dotnet)
1144+
1145+
#### Nexus Operations Backed by Workflows
1146+
1147+
To create a Nexus service with operations backed by workflows, first there needs to be a service contract, like so:
1148+
1149+
```csharp
1150+
using NexusRpc;
1151+
1152+
[NexusService]
1153+
public interface IGreetingService
1154+
{
1155+
[NexusOperation]
1156+
string SayHello(string name);
1157+
}
1158+
```
1159+
1160+
A service implementation can make this call backed by a workflow like so:
1161+
1162+
```csharp
1163+
using NexusRpc.Handlers;
1164+
using Temporalio.Nexus;
1165+
1166+
[NexusServiceHandler(typeof(IGreetingService))]
1167+
public class GreetingService
1168+
{
1169+
[NexusOperationHandler]
1170+
public IOperationHandler<string, string> SayHello() =>
1171+
// Creates an operation handler backed by a workflow handle factory
1172+
WorkflowRunOperationHandler.FromHandleFactory<string, string>((context, name) =>
1173+
// Context of the handle factory is used to start the workflow and
1174+
// return a handle
1175+
context.StartWorkflowAsync(
1176+
(MyGreetingWorkflow wf) => wf.RunAsync(name),
1177+
// ID is required
1178+
new() { Id = $"wf-{Guid.NewGuid()}" }));
1179+
}
1180+
```
1181+
1182+
Notes about Nexus operations backed by workflows:
1183+
1184+
* `WorkflowRunOperationHandler.FromHandleFactory` will create an operation handler that invokes the handle factory on
1185+
start and wires up operation token and cancellation properly.
1186+
* The context provided to the handle factory has `StartWorkflowAsync` calls that mimic the same ones on the Temporal
1187+
client. The context also provides access to the general Nexus start context.
1188+
* Users can mutate the input before sending to the workflow in the handle factory, but mutating the output is not
1189+
supported at this time and should be done in the workflow logic.
1190+
* For general Nexus service and operation handler information/documentation, see
1191+
[the Nexus .NET SDK repository](https://github.com/nexus-rpc/sdk-dotnet).
1192+
11241193
### OpenTelemetry Tracing Support
11251194

11261195
See the

src/Temporalio.Extensions.OpenTelemetry/TracingInterceptor.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ public ActivityInboundInterceptor InterceptActivity(
7575
ActivityInboundInterceptor nextInterceptor) =>
7676
new ActivityInbound(this, nextInterceptor);
7777

78+
/// <inheritdoc />
79+
public NexusOperationInboundInterceptor InterceptNexusOperation(
80+
NexusOperationInboundInterceptor nextInterceptor) =>
81+
// TODO(cretz): Tracing for Nexus operations - https://github.com/temporalio/sdk-dotnet/issues/515
82+
nextInterceptor;
83+
7884
/// <summary>
7985
/// Serialize an OTel context to Temporal headers.
8086
/// </summary>

0 commit comments

Comments
 (0)