Overview

There exists an issue concerning the cancellation of SignalR server-to-client requests. This problem often arises within Azure Functions due to a particular code structure. Let’s delve into the specifics:

public async Task<IActionResult> PostMessage([HttpTrigger(AuthorizationLevel.Function, "post", Route = "{userId}/data")] HttpRequestData req, Guid userId,
       CancellationToken cancellationToken)
{
    // some code
    await foreach (var result in _getCompletion.Handle(command, cancellationToken))
    {
        _logger.LogTrace("{method} Received answer from underlying layer: {completinResult.Content}.", nameof(method), result.Content);
        cancellationToken.ThrowIfCancellationRequested();
        // some code
        _logger.LogTrace("{method} Sending result to client.", nameof(method));
        await MessageHubContext.Clients.User(userId.ToString()).SendAsync(NewPartOfResultReceived, result, cancellationToken);
        _logger.LogTrace("{method} Sent answer to client", nameof(method));
    };
    // some code
    return new JsonResult(finalResult);
}

The core of the issue lies in SignalR’s behavior, wherein even after cancellation of the token (utilizing AbortSignal.abort()), SignalR persists in sending data to the client.

Identifying the Issue

It appears that SignalR lacks built-in support for cancellation in such scenarios. This observation has been documented in a GitHub ticket: dotnet/aspnetcore#11542.

Proposed Solution

To tackle this issue, one potential solution involves halting the reception of data for connections associated with an ‘aborted’ state in the AbortSignal. Rather than resolving the problem on the backend, it could be more feasible to address it on the client side.

Here’s a TypeScript snippet illustrating how you can check for an aborted signal and prevent further processing if found:

// some code
// state.operations contains current ongoing operations
const targetOperation = state.operations.find(x => x.id === allData[targetData].operationId);
if (targetOperation === undefined || targetOperation?.controller?.signal.aborted) {
    return;
}
// adding data to the target

By implementing a mechanism on the client side that ceases data reception upon detection of an aborted AbortSignal, the issue can be effectively mitigated.

  • The text was updated and modified by OpenAI/ GTP-3.5 model.