|
1 | 1 | // Copyright (c) Microsoft Corporation. |
2 | 2 | // Licensed under the MIT License. |
3 | 3 |
|
4 | | -using System.Diagnostics.CodeAnalysis; |
5 | 4 | using System.Text; |
6 | 5 | using DurableTask.Core; |
7 | 6 | using DurableTask.Core.Entities; |
8 | 7 | using DurableTask.Core.Entities.OperationFormat; |
9 | 8 | using DurableTask.Core.History; |
10 | | -using Grpc.Core; |
11 | 9 | using Microsoft.DurableTask.Entities; |
12 | 10 | using Microsoft.DurableTask.Worker.Shims; |
13 | 11 | using Microsoft.Extensions.DependencyInjection; |
@@ -186,10 +184,18 @@ async ValueTask<OrchestrationRuntimeState> BuildRuntimeStateAsync( |
186 | 184 |
|
187 | 185 | async Task ProcessWorkItemsAsync(AsyncServerStreamingCall<P.WorkItem> stream, CancellationToken cancellation) |
188 | 186 | { |
| 187 | + // Create a new token source for timing out and a final token source that keys off of them both. |
| 188 | + // The timeout token is used to detect when we are no longer getting any messages, including health checks. |
| 189 | + // If this is the case, it signifies the connection has been dropped silently and we need to reconnect. |
| 190 | + using var timeoutSource = new CancellationTokenSource(); |
| 191 | + timeoutSource.CancelAfter(TimeSpan.FromSeconds(60)); |
| 192 | + using var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellation, timeoutSource.Token); |
| 193 | + |
189 | 194 | while (!cancellation.IsCancellationRequested) |
190 | 195 | { |
191 | | - await foreach (P.WorkItem workItem in stream.ResponseStream.ReadAllAsync(cancellation)) |
| 196 | + await foreach (P.WorkItem workItem in stream.ResponseStream.ReadAllAsync(tokenSource.Token)) |
192 | 197 | { |
| 198 | + timeoutSource.CancelAfter(TimeSpan.FromSeconds(60)); |
193 | 199 | if (workItem.RequestCase == P.WorkItem.RequestOneofCase.OrchestratorRequest) |
194 | 200 | { |
195 | 201 | this.RunBackgroundTask( |
@@ -237,6 +243,20 @@ async Task ProcessWorkItemsAsync(AsyncServerStreamingCall<P.WorkItem> stream, Ca |
237 | 243 | this.Logger.UnexpectedWorkItemType(workItem.RequestCase.ToString()); |
238 | 244 | } |
239 | 245 | } |
| 246 | + |
| 247 | + if (tokenSource.IsCancellationRequested || tokenSource.Token.IsCancellationRequested) |
| 248 | + { |
| 249 | + // The token has cancelled, this means either: |
| 250 | + // 1. The broader 'cancellation' was triggered, return here to start a graceful shutdown. |
| 251 | + // 2. The timeoutSource was triggered, return here to trigger a reconnect to the backend. |
| 252 | + if (!cancellation.IsCancellationRequested) |
| 253 | + { |
| 254 | + // Since the cancellation came from the timeout, log a warning. |
| 255 | + this.Logger.ConnectionTimeout(); |
| 256 | + } |
| 257 | + |
| 258 | + return; |
| 259 | + } |
240 | 260 | } |
241 | 261 | } |
242 | 262 |
|
|
0 commit comments