Azure / azure-signalr

Azure SignalR Service SDK for .NET
https://aka.ms/signalr-service
MIT License
427 stars 101 forks source link

Azure SignalR InvokeAsync hangs when attempting to establish Group connection #1281

Open bizmonger opened 3 years ago

bizmonger commented 3 years ago

Calling InvokeAsync on a connection hangs.

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

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
zackliu commented 3 years ago

Your function is not correct to handle message. You need to add a function with SignalRTrigger to handle connection.InvokeAsync("JoinGroup", sessionId) Please refer document https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-signalr-service-trigger?tabs=csharp and sample https://github.com/aspnet/AzureSignalR-samples/tree/main/samples/BidirectionChat

vwxyzh commented 3 years ago

and please set the upstream correctly.

bizmonger commented 3 years ago

You mean do this? connection.InvokeAsync("JoinGroupFn", sessionId)