Azure SignalR Serverless - Trouble calling Durable Function when closing hub connection

91 views Asked by At

I established my Serverless Hub in a Durable Functions project. The methods in the hub include “Negotiate”, “AddUserToGroup” and “RemoveUserFromGroup”. “RemoveUserFromGroup” is called on browser close and when an “Route Guard” is crossed. And I am using a Durable Entity to store state.

I established my SignalR Client in an Angular Service using @microsoft/azure npm package.

My initial version included HttpTrigger calls for all three methods. And they all three were working locally. But when deployed to an environment in Azure, the “RemoveUserFromGroup” method became a problem. It worked fine when crossing a “Route Guard”. The issue is when the browser closes, the call gets lost due to the initiator being lost. As a result, the user is not removed from the SignalR Group, nor is the user removed from my Durable Entity.

`@HostListener('window:beforeunload', ['$event'])
  beforeunloadHandler(): void {
    if (this._signalRService.webpageUser)
      this._signalRService.removeUserFromGroup(this._signalRService.webpageUser);
  }`

According to my reading, I am not the only one to hit this challenge. I found the following article, suggesting I use Event Grid to initiate the “RemoveUserFromGroup” call.

https://devblogs.microsoft.com/dotnet/azure-signalr-service-now-supports-event-grid/

I understand Event Grid can make a direct call to SignalR or it can call “RemoveUserFromGroup” directly. The challenge I encountered is authorizing the call, from the Angular SignalR Client, to Event Grid.

More research led to an idea around using APIM as an intermediary between the Client and Event Grid.

I decided to review with my CTO as things felt complicated. He encouraged me to review the use of a SignalRTrigger for the “RemoveUserFromGroup” method. I had a bit of trouble, initially, understanding how the SignalRTrigger worked but I have it now. I understand the idea of an upstream endpoint with Hub, Category and Event.

I am using the SignalR Service emulator. Currently, I have established a SignalRTrigger in my “RemoveUserFromGroup” function. I have my Hub, Category and Event established in “settings.json”.

{
  "UpstreamSettings": {
    "Templates": [
      {
        "UrlTemplate": "http://localhost:7071/runtime/webhooks/signalr",
        "EventPattern": "removeUserFromGroup",
        "HubPattern": "WebpageTracking",
        "CategoryPattern": "messages"
      }
    ]
  }
}

And here is the call from the Angular SignalR Client.

private removeUserFromGroupEndpoint(
    user: WebpageUser
  ){
     this.hubConnection.send('removeUserFromGroup', user)
    .then(result => {
      console.log('success: ' + result);
    })
    .catch((err: unknown): void => {
      console.log('error occurred' + err);
    });
  }

Due to having a breakpoint in the “RemoveUserFromGroup” function, I know the function is not actually being called. Interestingly, the promise is returning success. I can see ‘success: ‘… in my browsers console. Despite the code not being called and no breakpoint hit. I am returning a bool value (result), from “RemoveUserFromGroup”, just to confirm it is not actually making it to the function. And finally, the user is not removed from my Durable Entity.

A couple things about my Auth strategies in case they may need correction. I am using the “AuthorizationLevel.Anonymous” on my “Negotiate” method, with Identity Management between my Durable Function and Azure SignalR Service. I am using “AuthorizationLevel.Function”, key authorization, on my “AddUserToGroup” HttpTrigger. I assume the auth established on the SignalR connection, in the client, will ensure the success of the SignalRTrigger call.

I hope there is enough information here to determine the problem with my approach.

Thank you for your help!

0

There are 0 answers