Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SignalR emulator #6793

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

cqnguy23
Copy link

@cqnguy23 cqnguy23 commented Nov 25, 2024

Description

Fixes #6676

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?
Microsoft Reviewers: Open in CodeFlow

Addresses issue #6676

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Nov 25, 2024
@davidfowl davidfowl requested a review from vicancy November 25, 2024 16:13
@cqnguy23
Copy link
Author

cqnguy23 commented Dec 2, 2024

@dotnet-policy-service agree company="Microsoft"

@vicancy
Copy link
Contributor

vicancy commented Dec 11, 2024

Hi @eerhardt @davidfowl Azure Function requires an app key code to invoke the SignalR trigger, e.g. <endpoint>/runtime/webhooks/signalr/?code=xxx, https://learn.microsoft.com/en-us/azure/azure-functions/function-keys-how-to?tabs=azure-portal#use-access-keys. Is this code value something that aspire supports/or planned to help get this app key out?

@eerhardt
Copy link
Member

Hi @eerhardt @davidfowl Azure Function requires an app key code to invoke the SignalR trigger, e.g. <endpoint>/runtime/webhooks/signalr/?code=xxx, https://learn.microsoft.com/en-us/azure/azure-functions/function-keys-how-to?tabs=azure-portal#use-access-keys. Is this code value something that aspire supports/or planned to help get this app key out?

We were just talking with @fabiocav yesterday about a similar scenario for HttpTriggers. .NET Aspire doesn't have support inbox today, but are discussing how it can be supported.

cc @captainsafia @DamianEdwards

@cqnguy23
Copy link
Author

Hi @eerhardt, could you help add this package Microsoft.Azure.Functions.Worker.Extensions.SignalRService to the package source? Getting this error when building the playground sample: Unable to find package Microsoft.Azure.Functions.Worker.Extensions.SignalRService. No packages exist with this id in source(s): dotnet-eng, dotnet-public, dotnet9, dotnet9-transport.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to the existing Azure Functions playground sample instead of creating a new one?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or collapse it into the existing SignalR playground app? I'm not sure we need 2 in the repo.

Also, is the "Functions" part of this superfluous? This PR is for the SignalR emulator. It might be overkill trying to define/decide how Functions and Azure SignalR work together in this PR. It will probably distract/delay getting the emulator support in.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe in one SignalR playground but creating 2 SignalR resources, one for serverless one for default mode. For Azure SignalR emulator, it works for serverless scenarios only, which mostly works together with Azure Function. I think it would be a great serverless sample if Function works. But yeah if Function SignalRTrigger is not yet ready, surely we could have a simpler sample for the serverless scenario to let the emulator support ready first.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But yeah if Function SignalRTrigger is not yet ready, surely we could have a simpler sample for the serverless scenario to let the emulator support ready first.

I'm inclined to pull out the Functions-specific changes from this PR and just leave the SignalR support. Supporting triggers for Functions in Aspire requires some additional work (see #6414). It would make review easier to scope this to just the SignalR-emulator specific changes and move the Functions changes to a separate PR.

Is there a way to validate the emulator locally without implementing a Functions app?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@captainsafia Sure. I can just spin up a simple web app to invoke API from emulator without using Functions

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@captainsafia removed the Functions out of the scope and used a web application to validate the emulator instead. Could you check again?

_logger.LogInformation($"{invocationContext.ConnectionId} has disconnected");
}

public class NewConnection
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Consider using a record type here.

/// Configures an Azure SignalR resource to be emulated. This resource requires an <see cref="AzureSignalRResource"/> to be added to the application model. Please note that the resource will be emulated in <b>Serverless mode</b>.
/// </summary>
/// <remarks>
/// This version of the package defaults to the <inheritdoc cref="SignalREmulatorContainerImageTags.Tag"/> tag of the <inheritdoc cref="SignalREmulatorContainerImageTags.Registry"/>/<inheritdoc cref="SignalREmulatorContainerImageTags.Image"/> container image.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI - @sebastienros - this will need to be fixed with #6747

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could I just fix it in this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebastienros do we know what the right fix is?

src/Aspire.Hosting.Azure.SignalR/AzureSignalRExtensions.cs Outdated Show resolved Hide resolved
src/Aspire.Hosting.Azure.SignalR/AzureSignalRExtensions.cs Outdated Show resolved Hide resolved
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace Aspire.Hosting.Azure.SignalR;
internal sealed class AzureSignalRHealthCheck : IHealthCheck
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any thoughts on contributing this health check to https://github.com/xabaril/AspNetCore.Diagnostics.HealthChecks/? It doesn't need to block this PR, but the idea is that having a rich library of health checks (outside of Aspire) helps the whole community.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Azure SignalR has it's own SDK with HealthCheck embeded, this class might be only useful for this emulator scenario.

Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking pretty good. I pulled it locally, and it all worked for me.

Thanks for the contribution!

@cqnguy23 cqnguy23 requested a review from eerhardt January 6, 2025 04:52
Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks @cqnguy23!

@eerhardt
Copy link
Member

eerhardt commented Jan 6, 2025

However, it looks like the new test is failing:

Microsoft.Azure.SignalR.Common.AzureSignalRException : An error happened when making request to http://localhost:46185/api/health?api-version=2022-06-01
---- System.Net.Http.HttpRequestException : An error occurred while sending the request.
-------- System.IO.IOException : Unable to read data from the transport connection: Connection reset by peer.
------------ System.Net.Sockets.SocketException : Connection reset by peer



Stack trace
   at Microsoft.Azure.SignalR.RestClient.SendAsyncCore(String httpClientName, RestApiEndpoint api, HttpMethod httpMethod, String methodName, Object[] args, Func`2 handleExpectedResponseAsync, CancellationToken cancellationToken)
   at Microsoft.Azure.SignalR.Management.ServiceManagerImpl.IsServiceHealthy(CancellationToken cancellationToken)
   at Aspire.Hosting.Azure.Tests.AzureSignalREmulatorFunctionalTest.VerifyAzureSignalREmulatorResource() in /_/tests/Aspire.Hosting.Azure.Tests/AzureSignalREmulatorFunctionalTest.cs:line 91
--- End of stack trace from previous location ---
----- Inner Stack Trace -----
   at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.<SendCoreAsync>g__Core|5_0(HttpRequestMessage request, Boolean useAsync, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.<SendCoreAsync>g__Core|5_0(HttpRequestMessage request, Boolean useAsync, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at Microsoft.Azure.SignalR.RestClient.SendAsyncCore(String httpClientName, RestApiEndpoint api, HttpMethod httpMethod, String methodName, Object[] args, Func`2 handleExpectedResponseAsync, CancellationToken cancellationToken)
----- Inner Stack Trace -----
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
   at System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)
   at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
----- Inner Stack Trace ----

Can you take a look?

@cqnguy23
Copy link
Author

cqnguy23 commented Jan 7, 2025

However, it looks like the new test is failing:

Microsoft.Azure.SignalR.Common.AzureSignalRException : An error happened when making request to http://localhost:46185/api/health?api-version=2022-06-01
---- System.Net.Http.HttpRequestException : An error occurred while sending the request.
-------- System.IO.IOException : Unable to read data from the transport connection: Connection reset by peer.
------------ System.Net.Sockets.SocketException : Connection reset by peer



Stack trace
   at Microsoft.Azure.SignalR.RestClient.SendAsyncCore(String httpClientName, RestApiEndpoint api, HttpMethod httpMethod, String methodName, Object[] args, Func`2 handleExpectedResponseAsync, CancellationToken cancellationToken)
   at Microsoft.Azure.SignalR.Management.ServiceManagerImpl.IsServiceHealthy(CancellationToken cancellationToken)
   at Aspire.Hosting.Azure.Tests.AzureSignalREmulatorFunctionalTest.VerifyAzureSignalREmulatorResource() in /_/tests/Aspire.Hosting.Azure.Tests/AzureSignalREmulatorFunctionalTest.cs:line 91
--- End of stack trace from previous location ---
----- Inner Stack Trace -----
   at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.<SendCoreAsync>g__Core|5_0(HttpRequestMessage request, Boolean useAsync, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.<SendCoreAsync>g__Core|5_0(HttpRequestMessage request, Boolean useAsync, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at Microsoft.Azure.SignalR.RestClient.SendAsyncCore(String httpClientName, RestApiEndpoint api, HttpMethod httpMethod, String methodName, Object[] args, Func`2 handleExpectedResponseAsync, CancellationToken cancellationToken)
----- Inner Stack Trace -----
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
   at System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)
   at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
----- Inner Stack Trace ----

Can you take a look?

Can you help me re-run the tests? I encountered this error a few times and found that re-running the tests would solve it.

@eerhardt
Copy link
Member

eerhardt commented Jan 7, 2025

I encountered this error a few times and found that re-running the tests would solve it.

We need our tests to be consistent and stable. If there is a problem, we should add retries/waits to the test code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add RunAsEmulator() method to wire up Azure SignalR's local emulator
5 participants