/// <inheritdoc /> public async Task <BoolResult> ShutdownAsync(Context context) { ShutdownStarted = true; try { _heartbeatTimer?.Dispose(); if (_sessionState == null) { // _sessionState is null if initialization has failed. return(BoolResult.Success); } StructResult <int> sessionResult = await _sessionState.GetIdAsync(); if (!sessionResult.Succeeded) { return(new BoolResult(sessionResult)); } int sessionId = sessionResult.Data; if (_serviceUnavailable) { context.Debug("Skipping session shutdown because service is unavailable."); } else { try { await _client.ShutdownSessionAsync(new ShutdownRequest { Header = new RequestHeader(context.Id, sessionId) }); } catch (RpcException e) { context.Error($"Failed to shut down session with error: {e}"); } } await _channel.ShutdownAsync(); ShutdownCompleted = true; return(BoolResult.Success); } catch (Exception ex) { // Catching all exceptions, even ClientCanRetryExceptions, because the teardown steps aren't idempotent. // In the worst case, the shutdown call comes while the service is offline, the service never receives it, // and then the service times out the session 10 minutes later (by default). ShutdownCompleted = true; return(new BoolResult(ex)); } }
/// <inheritdoc /> protected override AsyncUnaryCall <ShutdownResponse> ShutdownSessionAsync(ShutdownRequest shutdownRequest) { return(_client.ShutdownSessionAsync(shutdownRequest)); }