Azure SignalR InvokeAsync hangs when attempting to establish Group connection

1.1k Views Asked by At

Calling InvokeAsync on a connection hangs.

I'm referencing the following document to configure a group connection in Azure SignalR.

NOTE:

I am only able to establish a connection when NOT relying on a group configuration.

Client:

var negotiateJson = await _client.GetStringAsync($"{host}{"negotiatefn"}");
var negotiate     = JsonConvert.DeserializeObject<NegotiateInfo>(negotiateJson);

var connection = new HubConnectionBuilder()
    .AddNewtonsoftJsonProtocol()
    .WithUrl(negotiate.Url, options => options.AccessTokenProvider = async () => negotiate.AccessToken)
    .Build();

connection.Closed -= Connection_Closed;
connection.Closed += Connection_Closed;

connection.On<JObject>(hubMethodName, OnCourierUpdate);

await connection.StartAsync();
await connection.InvokeAsync("JoinGroup", sessionId); // HANGS APP HERE !!!

Server: Azure Function

public static class LocationFn
{
    [FunctionName(nameof(LocationFn))]
    public static async Task<IActionResult> Run(
        [HttpTrigger(
            AuthorizationLevel.Anonymous,
            "post",
            Route = nameof(LocationFn))]
        HttpRequest req,
        [SignalR(HubName = "LocationHub")]
        IAsyncCollector<SignalRMessage> signalRMessages,
        ILogger log)
    {
        log.LogInformation($"{nameof(LocationFn)} has been invoked.");

        try
        {
            using (var streamReader = new StreamReader(req.Body))
            {
                var json = await streamReader.ReadToEndAsync();
                var subjectLocation = JsonConvert.DeserializeObject<SubjectLocation>(json);

                await signalRMessages.AddAsync(
                    new SignalRMessage
                    {
                        Target    = "LocationUpdate",
                        GroupName = subjectLocation.SessionId,
                        Arguments = new[] { subjectLocation }
                    });

                var message = Log(log, subjectLocation);

                return new OkObjectResult(message);
            }
        }
        catch (Exception ex)
        {
            return new BadRequestObjectResult("There was an error: " + ex.Message);
        }
    }
}



public static class JoinGroupFn
{
    [FunctionName(nameof(JoinGroupFn))]
    public static async Task<IActionResult> Run(
        [HttpTrigger(
            AuthorizationLevel.Anonymous,
            "post",
            Route = nameof(JoinGroupFn))]
        HttpRequest req,
        [SignalR(HubName = "LocationHub")]
        IAsyncCollector<SignalRMessage> signalRMessages,
        ILogger log)
    {
        log.LogInformation($"{nameof(JoinGroupFn)} has been invoked.");

        try
        {
            var groupId = await req.ReadAsStringAsync();

            await signalRMessages.AddAsync(
                new SignalRMessage
                {
                    Target    = "JoinGroup",
                    GroupName = groupId,
                    Arguments = new[] { groupId }
                });

            log.LogInformation($"{nameof(JoinGroupFn)} {groupId}");

            return new OkObjectResult(groupId);
        }
        catch (Exception ex)
        {
            return new BadRequestObjectResult("There was an error: " + ex.Message);
        }
    }
}

Server: Hub

type LocationHub() as x =

    inherit Hub()

    let this = (x :> Hub)

    member x.LocationUpdate(v:SubjectLocation) =

        async { do! this.Clients.Group(v.SessionId).SendAsync("LocationUpdate", v) |> Async.AwaitTask

              } |> Async.StartAsTask

    member x.JoinGroup(groupId:string) =

        async { do! this.Groups.AddToGroupAsync(this.Context.ConnectionId, groupId) |> Async.AwaitTask

              } |> Async.StartAsTask
1

There are 1 best solutions below

3
On

Im from Azure SignalR team, your service is running in Serverless mode, it do not allow any server connection, how can your F# hub run?

And in client side, connection.InvokeAsync require server ack, since the server connection can not connected, it cannot get any ack from service.

If you need hub server, please switch the service to Default mode, then run hub with Azure SignalR SDK, and verify the server is connected (by log or connection count in service metrics).

If you want serverless, please remove the hub, you can add a Serverless hub in Functions side, see: https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-concept-serverless-development-config#class-based-model. And do not forget to set the upstream, see: https://learn.microsoft.com/en-us/azure/azure-signalr/concept-upstream#rule-settings.