Skip to content

Commit

Permalink
Stop accepting JsonRpc requests during shutdown (#7818)
Browse files Browse the repository at this point in the history
  • Loading branch information
benaadams authored Nov 26, 2024
1 parent 9780259 commit 39d8076
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/Nethermind/Nethermind.Config/IProcessExitSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public interface IProcessExitSource

public class ProcessExitSource : IProcessExitSource
{
private static readonly CancellationToken _cancelledToken = new(canceled: true);
private CancellationTokenSource _cancellationTokenSource;
private readonly TaskCompletionSource _exitResult = new();

Expand All @@ -38,5 +39,5 @@ public void Exit(int exitCode)

public Task ExitTask => _exitResult.Task;

public CancellationToken Token => _cancellationTokenSource.Token;
public CancellationToken Token => _cancellationTokenSource?.Token ?? _cancelledToken;
}
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.JsonRpc/IJsonRpcProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@

using System.Collections.Generic;
using System.IO.Pipelines;
using System.Threading;

namespace Nethermind.JsonRpc;

public interface IJsonRpcProcessor
{
IAsyncEnumerable<JsonRpcResult> ProcessAsync(PipeReader stream, JsonRpcContext context);
CancellationToken ProcessExit { get; }
}
15 changes: 14 additions & 1 deletion src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http;
using Nethermind.Config;
using Nethermind.Core.Collections;
using Nethermind.Core.Extensions;
using Nethermind.Core.Resettables;
Expand All @@ -30,15 +31,18 @@ public class JsonRpcProcessor : IJsonRpcProcessor
private readonly ILogger _logger;
private readonly IJsonRpcService _jsonRpcService;
private readonly Recorder _recorder;
private readonly IProcessExitSource? _processExitSource;

public JsonRpcProcessor(IJsonRpcService jsonRpcService, IJsonRpcConfig jsonRpcConfig, IFileSystem fileSystem, ILogManager logManager)
public JsonRpcProcessor(IJsonRpcService jsonRpcService, IJsonRpcConfig jsonRpcConfig, IFileSystem fileSystem, ILogManager logManager, IProcessExitSource? processExitSource = null)
{
_logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager));
ArgumentNullException.ThrowIfNull(fileSystem);

_jsonRpcService = jsonRpcService ?? throw new ArgumentNullException(nameof(jsonRpcService));
_jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig));

_processExitSource = processExitSource;

if (_jsonRpcConfig.RpcRecorderState != RpcRecorderState.None)
{
if (_logger.IsWarn) _logger.Warn("Enabling JSON RPC diagnostics recorder - this will affect performance and should be only used in a diagnostics mode.");
Expand All @@ -47,6 +51,9 @@ public JsonRpcProcessor(IJsonRpcService jsonRpcService, IJsonRpcConfig jsonRpcCo
}
}

public CancellationToken ProcessExit
=> _processExitSource?.Token ?? default;

private (JsonRpcRequest? Model, ArrayPoolList<JsonRpcRequest>? Collection) DeserializeObjectOrArray(JsonDocument doc)
{
JsonValueKind type = doc.RootElement.ValueKind;
Expand Down Expand Up @@ -120,6 +127,12 @@ private ArrayPoolList<JsonRpcRequest> DeserializeArray(JsonElement element) =>

public async IAsyncEnumerable<JsonRpcResult> ProcessAsync(PipeReader reader, JsonRpcContext context)
{
if (ProcessExit.IsCancellationRequested)
{
JsonRpcErrorResponse response = _jsonRpcService.GetErrorResponse(ErrorCodes.ResourceUnavailable, "Shutting down");
yield return JsonRpcResult.Single(RecordResponse(response, new RpcReport("Shutdown", 0, false)));
}

reader = await RecordRequest(reader);
long startTime = Stopwatch.GetTimestamp();
CancellationTokenSource timeoutSource = new(_jsonRpcConfig.Timeout);
Expand Down
3 changes: 2 additions & 1 deletion src/Nethermind/Nethermind.Runner/Ethereum/Steps/StartRpc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public async Task Execute(CancellationToken cancellationToken)
jsonRpcService,
jsonRpcConfig,
_api.FileSystem,
_api.LogManager);
_api.LogManager,
_api.ProcessExit);


if (initConfig.WebSocketsEnabled)
Expand Down
6 changes: 6 additions & 0 deletions src/Nethermind/Nethermind.Runner/JsonRpc/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IJsonRpc
return;
}

if (jsonRpcProcessor.ProcessExit.IsCancellationRequested)
{
ctx.Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
return;
}

if (!jsonRpcUrlCollection.TryGetValue(ctx.Connection.LocalPort, out JsonRpcUrl jsonRpcUrl) ||
!jsonRpcUrl.RpcEndpoint.HasFlag(RpcEndpoint.Http))
{
Expand Down

0 comments on commit 39d8076

Please sign in to comment.