Skip to content

Commit e8b3e66

Browse files
committed
Used the ApplicationStopping cancellation token for gracefully terminating "Watch" streams on server shutdown
1 parent 3bb5144 commit e8b3e66

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

src/Grpc.AspNetCore.HealthChecks/HealthServiceImpl.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Grpc.Core;
2020
using Grpc.Core.Utils;
2121
using Grpc.Health.V1;
22+
using Microsoft.Extensions.Hosting;
2223

2324
namespace Grpc.AspNetCore.HealthChecks;
2425

@@ -32,7 +33,7 @@ namespace Grpc.AspNetCore.HealthChecks;
3233
/// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl));
3334
/// </code>
3435
/// </summary>
35-
public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase
36+
public class HealthServiceImpl(IHostApplicationLifetime applicationLifetime) : Grpc.Health.V1.Health.HealthBase
3637
{
3738
// The maximum number of statuses to buffer on the server.
3839
internal const int MaxStatusBufferSize = 5;
@@ -192,15 +193,22 @@ public override async Task Watch(HealthCheckRequest request, IServerStreamWriter
192193
HealthCheckResponse response = GetHealthCheckResponse(service, throwOnNotFound: false);
193194
await responseStream.WriteAsync(response).ConfigureAwait(false);
194195

195-
// Read messages. WaitToReadAsync will wait until new messages are available.
196-
// Loop will exit when the call is canceled and the writer is marked as complete.
197-
while (await channel.Reader.WaitToReadAsync().ConfigureAwait(false))
196+
try
198197
{
199-
if (channel.Reader.TryRead(out HealthCheckResponse? item))
198+
// Read messages. WaitToReadAsync will wait until new messages are available.
199+
// Loop will exit when the call is canceled and the writer is marked as complete or when the application is stopping.
200+
while (await channel.Reader.WaitToReadAsync(applicationLifetime.ApplicationStopping).ConfigureAwait(false))
200201
{
201-
await responseStream.WriteAsync(item).ConfigureAwait(false);
202+
if (channel.Reader.TryRead(out HealthCheckResponse? item))
203+
{
204+
await responseStream.WriteAsync(item).ConfigureAwait(false);
205+
}
202206
}
203207
}
208+
catch (OperationCanceledException)
209+
{
210+
await responseStream.WriteAsync(new HealthCheckResponse { Status = HealthCheckResponse.Types.ServingStatus.NotServing });
211+
}
204212
}
205213

206214
private void NotifyStatus(string service, HealthCheckResponse.Types.ServingStatus status)

0 commit comments

Comments
 (0)