Skip to content

Commit 8efb708

Browse files
authored
Update protobuf, add suspend and resume event support (#97)
1 parent 64ea918 commit 8efb708

File tree

10 files changed

+110
-4
lines changed

10 files changed

+110
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## v1.0.0
44

5+
- Added `SuspendInstanceAsync` and `ResumeInstanceAsync` to `DurableTaskClient`.
56
- `TaskOrchestrationContext.CreateReplaySafeLogger` now creates `ILogger` directly (as opposed to wrapping an existing `ILogger`).
67
- Durable Functions class-based syntax now resolves `ITaskActivity` instances from `IServiceProvider`, if available there.
78
- `DurableTaskClient` methods have been touched up to ensure `CancellationToken` is included, as well as is the last parameter.

src/Client/Core/DurableTaskClient.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,33 @@ public virtual Task<OrchestrationMetadata> WaitForInstanceStartAsync(
178178
string instanceId, CancellationToken cancellation)
179179
=> this.WaitForInstanceStartAsync(instanceId, false, cancellation);
180180

181+
/// <summary>
182+
/// Suspends an orchestration instance, halting processing of it until <see cref="ResumeInstanceAsync" /> is used
183+
/// to resume the orchestration.
184+
/// </summary>
185+
/// <param name="instanceId">The instance ID of the orchestration to suspend.</param>
186+
/// <param name="reason">The optional suspension reason.</param>
187+
/// <param name="cancellation">
188+
/// A <see cref="CancellationToken"/> that can be used to cancel the suspend operation. Note, cancelling this token
189+
/// does <b>not</b> resume the orchestration if suspend was successful.
190+
/// </param>
191+
/// <returns>A task that completes when the suspend has been committed to the backend.</returns>
192+
public abstract Task SuspendInstanceAsync(
193+
string instanceId, string? reason = null, CancellationToken cancellation = default);
194+
195+
/// <summary>
196+
/// Resumes an orchestration instance that was suspended via <see cref="SuspendInstanceAsync" />.
197+
/// </summary>
198+
/// <param name="instanceId">The instance ID of the orchestration to resume.</param>
199+
/// <param name="reason">The optional resume reason.</param>
200+
/// <param name="cancellation">
201+
/// A <see cref="CancellationToken"/> that can be used to cancel the resume operation. Note, cancelling this token
202+
/// does <b>not</b> re-suspend the orchestration if resume was successful.
203+
/// </param>
204+
/// <returns>A task that completes when the resume has been committed to the backend.</returns>
205+
public abstract Task ResumeInstanceAsync(
206+
string instanceId, string? reason = null, CancellationToken cancellation = default);
207+
181208
/// <summary>
182209
/// Waits for an orchestration to start running and returns a <see cref="OrchestrationMetadata"/>
183210
/// object that contains metadata about the started instance.

src/Client/Core/OrchestrationRuntimeStatus.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,9 @@ public enum OrchestrationRuntimeStatus
4444
/// The orchestration was scheduled but hasn't started running.
4545
/// </summary>
4646
Pending,
47+
48+
/// <summary>
49+
/// The orchestration is in a suspended state.
50+
/// </summary>
51+
Suspended,
4752
}

src/Client/Grpc/Client.Grpc.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
</PropertyGroup>
1414

1515
<ItemGroup>
16-
<PackageReference Include="Grpc.Core" Version="2.39.1" />
17-
<PackageReference Include="Microsoft.DurableTask.Sidecar.Protobuf" Version="0.3.1" />
16+
<PackageReference Include="Microsoft.DurableTask.Sidecar.Protobuf" Version="1.0.0" />
1817
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
1918
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
2019
</ItemGroup>

src/Client/Grpc/GrpcDurableTaskClient.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,50 @@ await this.sidecarClient.TerminateInstanceAsync(
136136
cancellationToken: cancellation);
137137
}
138138

139+
/// <inheritdoc/>
140+
public override async Task SuspendInstanceAsync(
141+
string instanceId, string? reason = null, CancellationToken cancellation = default)
142+
{
143+
P.SuspendRequest request = new()
144+
{
145+
InstanceId = instanceId,
146+
Reason = reason,
147+
};
148+
149+
try
150+
{
151+
await this.sidecarClient.SuspendInstanceAsync(
152+
request, cancellationToken: cancellation);
153+
}
154+
catch (RpcException e) when (e.StatusCode == StatusCode.Cancelled)
155+
{
156+
throw new OperationCanceledException(
157+
$"The {nameof(this.SuspendInstanceAsync)} operation was canceled.", e, cancellation);
158+
}
159+
}
160+
161+
/// <inheritdoc/>
162+
public override async Task ResumeInstanceAsync(
163+
string instanceId, string? reason = null, CancellationToken cancellation = default)
164+
{
165+
P.ResumeRequest request = new()
166+
{
167+
InstanceId = instanceId,
168+
Reason = reason,
169+
};
170+
171+
try
172+
{
173+
await this.sidecarClient.ResumeInstanceAsync(
174+
request, cancellationToken: cancellation);
175+
}
176+
catch (RpcException e) when (e.StatusCode == StatusCode.Cancelled)
177+
{
178+
throw new OperationCanceledException(
179+
$"The {nameof(this.ResumeInstanceAsync)} operation was canceled.", e, cancellation);
180+
}
181+
}
182+
139183
/// <inheritdoc/>
140184
public override async Task<OrchestrationMetadata?> GetInstanceMetadataAsync(
141185
string instanceId, bool getInputsAndOutputs = false, CancellationToken cancellation = default)

src/Client/Grpc/ProtoUtils.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ internal static P.OrchestrationStatus ToGrpcStatus(this OrchestrationRuntimeStat
7171
OrchestrationRuntimeStatus.Pending => P.OrchestrationStatus.Pending,
7272
OrchestrationRuntimeStatus.Running => P.OrchestrationStatus.Running,
7373
OrchestrationRuntimeStatus.Terminated => P.OrchestrationStatus.Terminated,
74+
OrchestrationRuntimeStatus.Suspended => P.OrchestrationStatus.Suspended,
7475
_ => throw new ArgumentOutOfRangeException(nameof(status), "Unexpected value"),
7576
};
7677
#pragma warning restore 0618 // Referencing Obsolete member.

src/Shared/Grpc/ProtoUtils.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ internal static HistoryEvent ConvertHistoryEvent(P.HistoryEvent proto)
6060
case P.HistoryEvent.EventTypeOneofCase.ExecutionTerminated:
6161
historyEvent = new ExecutionTerminatedEvent(proto.EventId, proto.ExecutionTerminated.Input);
6262
break;
63+
case P.HistoryEvent.EventTypeOneofCase.ExecutionSuspended:
64+
historyEvent = new ExecutionSuspendedEvent(proto.EventId, proto.ExecutionSuspended.Input);
65+
break;
66+
case P.HistoryEvent.EventTypeOneofCase.ExecutionResumed:
67+
historyEvent = new ExecutionResumedEvent(proto.EventId, proto.ExecutionResumed.Input);
68+
break;
6369
case P.HistoryEvent.EventTypeOneofCase.TaskScheduled:
6470
historyEvent = new TaskScheduledEvent(
6571
proto.EventId,

src/Worker/Grpc/Worker.Grpc.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@
1313
</PropertyGroup>
1414

1515
<ItemGroup>
16-
<PackageReference Include="Grpc.Core" Version="2.39.1" />
1716
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
1817
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
19-
<PackageReference Include="Microsoft.DurableTask.Sidecar.Protobuf" Version="0.3.1" />
18+
<PackageReference Include="Microsoft.DurableTask.Sidecar.Protobuf" Version="1.0.0" />
2019
<PackageReference Include="System.Collections.Immutable" Version="6.0.0" />
2120
</ItemGroup>
2221

test/Client/Core.Tests/DependencyInjection/DefaultDurableTaskClientBuilderTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ public override Task RaiseEventAsync(
106106
throw new NotImplementedException();
107107
}
108108

109+
public override Task ResumeInstanceAsync(
110+
string instanceId, string? reason = null, CancellationToken cancellation = default)
111+
{
112+
throw new NotImplementedException();
113+
}
114+
109115
public override Task<string> ScheduleNewOrchestrationInstanceAsync(
110116
TaskName orchestratorName,
111117
object? input = null,
@@ -115,6 +121,12 @@ public override Task<string> ScheduleNewOrchestrationInstanceAsync(
115121
throw new NotImplementedException();
116122
}
117123

124+
public override Task SuspendInstanceAsync(
125+
string instanceId, string? reason = null, CancellationToken cancellation = default)
126+
{
127+
throw new NotImplementedException();
128+
}
129+
118130
public override Task TerminateAsync(
119131
string instanceId, object? output = null, CancellationToken cancellation = default)
120132
{

test/Client/Core.Tests/DependencyInjection/DurableTaskClientBuilderExtensionsTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ public override Task RaiseEventAsync(
136136
throw new NotImplementedException();
137137
}
138138

139+
public override Task ResumeInstanceAsync(
140+
string instanceId, string? reason = null, CancellationToken cancellation = default)
141+
{
142+
throw new NotImplementedException();
143+
}
144+
139145
public override Task<string> ScheduleNewOrchestrationInstanceAsync(
140146
TaskName orchestratorName,
141147
object? input = null,
@@ -145,6 +151,12 @@ public override Task<string> ScheduleNewOrchestrationInstanceAsync(
145151
throw new NotImplementedException();
146152
}
147153

154+
public override Task SuspendInstanceAsync(
155+
string instanceId, string? reason = null, CancellationToken cancellation = default)
156+
{
157+
throw new NotImplementedException();
158+
}
159+
148160
public override Task TerminateAsync(
149161
string instanceId, object? output = null, CancellationToken cancellation = default)
150162
{

0 commit comments

Comments
 (0)