Skip to content

Commit b8b0121

Browse files
authored
Refactor the build method of ServiceManager to remove internal dependency (Azure#33158)
<!-- DO NOT DELETE THIS TEMPLATE --> ## Description <!-- Please add an informative description that covers that changes made by the pull request. If you are regenerating your SDK based off of a new swagger spec, please add the link to the corresponding swagger spec pull request that has been merged in the azure-rest-api-specs repository --> In ServiceManagerStore.cs, refactor the build method of ServiceManager to remove internal dependency. The original implementation builds the ServiceManager from a ServiceCollection directly, and inject IConfigureOptions<ServiceManagerOptions> and IOptionsChangeTokenSource<ServiceManagerOptions> to support hot reload. Without internal depdencies, we have to use the ServiceManagerBuilder to support hot-reload. The only way of ServiceManagerBuilder to support hot-reload is to inject a IConfiguration object which provides a change token. However, the SDK and function extensions have different ways to parse configuration, for example, SDK lacks the functionality to parse identity-based connection from configuration. Therefore, we have to pass the actual configuration action via ServiceManagerBuilder.WithOptions, and injects an IConfiguration object to provide change token. To avoid errors thrown by SDK when it parses the configuration, we wraps the real IConfiguration object to make it looks like empty configuration but provides the true change token. --- This checklist is used to make sure that common guidelines for a pull request are followed. - [ ] Please add REST spec PR link to the SDK PR - [x] **I have read the [contribution guidelines](https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md).** - [x] **The pull request does not introduce [breaking changes](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/breaking-change-rules.md).** ### [General Guidelines](https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md#general-guidelines) - [x] Title of the pull request is clear and informative. - [x] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### [Testing Guidelines](https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md#testing-guidelines) - [x] Pull request includes test coverage for the included changes. ### [SDK Generation Guidelines](https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md#sdk-generation-guidelines) - [ ] If an SDK is being regenerated based on a new swagger spec, a link to the pull request containing these swagger spec changes has been included above. - [ ] The generate.cmd file for the SDK has been updated with the version of AutoRest, as well as the commitid of your swagger spec or link to the swagger spec, used to generate the code. - [ ] The `*.csproj` and `AssemblyInfo.cs` files have been updated with the new version of the SDK.
1 parent ad1a683 commit b8b0121

File tree

8 files changed

+32
-43
lines changed

8 files changed

+32
-43
lines changed

eng/Packages.Data.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@
130130
<PackageReference Update="CloudNative.CloudEvents.SystemTextJson" Version="2.0.0" />
131131
<PackageReference Update="MessagePack" Version="1.9.11" />
132132
<PackageReference Update="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="1.1.5" />
133-
<PackageReference Update="Microsoft.Azure.SignalR" Version="1.18.0" />
134-
<PackageReference Update="Microsoft.Azure.SignalR.Management" Version="1.18.0" />
135-
<PackageReference Update="Microsoft.Azure.SignalR.Protocols" Version="1.18.0" />
133+
<PackageReference Update="Microsoft.Azure.SignalR" Version="1.19.2" />
134+
<PackageReference Update="Microsoft.Azure.SignalR.Management" Version="1.19.2" />
135+
<PackageReference Update="Microsoft.Azure.SignalR.Protocols" Version="1.19.2" />
136136
<PackageReference Update="Microsoft.Azure.SignalR.Serverless.Protocols" Version="1.9.0" />
137137
<PackageReference Update="Microsoft.Azure.WebJobs" Version="3.0.33" />
138138
<PackageReference Update="Microsoft.Azure.WebJobs.Sources" Version="3.0.30" />

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Bindings/SignalRInputBindings/SignalREndpointsInputBinding/SignalREndpointsAsyncConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public async Task<ServiceEndpoint[]> ConvertAsync(SignalREndpointsAttribute inpu
2222
{
2323
var hubContext = await _serviceManagerStore
2424
.GetOrAddByConnectionStringKey(input.ConnectionStringSetting)
25-
.GetAsync(input.HubName).ConfigureAwait(false) as IInternalServiceHubContext;
25+
.GetAsync(input.HubName).ConfigureAwait(false) as ServiceHubContext;
2626
return hubContext.GetServiceEndpoints().ToArray();
2727
}
2828
}

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Bindings/SignalRInputBindings/SignalRMultiConnectionInfoBinding/NegotiationContextAsyncConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public async Task<NegotiationContext> ConvertAsync(
2424
{
2525
var serviceHubContext = await _serviceManagerStore
2626
.GetOrAddByConnectionStringKey(input.ConnectionStringSetting)
27-
.GetAsync(input.HubName).ConfigureAwait(false) as IInternalServiceHubContext;
27+
.GetAsync(input.HubName).ConfigureAwait(false) as ServiceHubContext;
2828
var endpoints = serviceHubContext.GetServiceEndpoints();
2929
var endpointConnectionInfo = await Task.WhenAll(endpoints.Select(async e =>
3030
{

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Client/AzureSignalRClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ private static IEnumerable<Claim> BuildJwtClaims(IEnumerable<Claim> customerClai
197197

198198
private async Task InvokeAsync(ServiceEndpoint[] endpoints, Func<ServiceHubContext, Task> func)
199199
{
200-
var targetHubContext = endpoints == null ? _serviceHubContext : (_serviceHubContext as IInternalServiceHubContext).WithEndpoints(endpoints);
200+
var targetHubContext = endpoints == null ? _serviceHubContext : _serviceHubContext.WithEndpoints(endpoints);
201201
await func.Invoke(targetHubContext).ConfigureAwait(false);
202202
}
203203
}

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Config/OptionsSetup.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System;
55
using System.Linq;
6-
using Microsoft.Azure.SignalR;
76
using Microsoft.Azure.SignalR.Management;
87
using Microsoft.Extensions.Azure;
98
using Microsoft.Extensions.Configuration;
@@ -62,17 +61,9 @@ public OptionsSetup(IConfiguration configuration, AzureComponentFactory azureCom
6261
}
6362
//make connection more stable
6463
options.ConnectionCount = 3;
65-
options.ProductInfo = GetProductInfo();
6664
};
6765
}
6866

6967
public Action<ServiceManagerOptions> Configure => _configureServiceManagerOptions;
70-
71-
private string GetProductInfo()
72-
{
73-
var workerRuntime = _configuration[Constants.FunctionsWorkerRuntime];
74-
var sdkProductInfo = ProductInfo.GetProductInfo();
75-
return $"{sdkProductInfo} [{Constants.FunctionsWorkerProductInfoKey}={workerRuntime}]";
76-
}
7768
}
7869
}

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Config/ServiceManagerStore.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,21 @@ public IInternalServiceHubContextStore GetByConfigurationKey(string connectionSt
5050
private IInternalServiceHubContextStore CreateHubContextStore(string connectionStringKey)
5151
{
5252
var serviceManagerOptionsSetup = new OptionsSetup(_configuration, _azureComponentFactory, connectionStringKey, _options);
53-
var serviceManger = new ServiceManagerBuilder()
53+
var serviceManagerBuilder = new ServiceManagerBuilder()
5454
// Does the actual configuration
5555
.WithOptions(serviceManagerOptionsSetup.Configure)
5656
.WithLoggerFactory(_loggerFactory)
57-
.WithRouter(_router ?? new EndpointRouterDecorator())
5857
// Serves as a reload token provider only
5958
.WithConfiguration(new EmptyConfiguration(_configuration))
60-
.BuildServiceManager();
59+
.WithCallingAssembly();
60+
AddWorkingInfo(serviceManagerBuilder, _configuration);
61+
if (_router != null)
62+
{
63+
serviceManagerBuilder.WithRouter(_router);
64+
}
65+
var serviceManager = serviceManagerBuilder.BuildServiceManager();
6166
return new ServiceCollection()
62-
.AddSingleton(serviceManger)
67+
.AddSingleton(serviceManager)
6368
.AddOptions()
6469
.AddSingleton<IConfigureOptions<SignatureValidationOptions>>(new SignatureValidationOptionsSetup(serviceManagerOptionsSetup.Configure))
6570
.AddSingleton<IOptionsChangeTokenSource<SignatureValidationOptions>>(new ConfigurationChangeTokenSource<SignatureValidationOptions>(_configuration))
@@ -82,5 +87,14 @@ public void Dispose()
8287
DisposeAsync().GetAwaiter().GetResult();
8388
#pragma warning restore AZC0102 // Do not use GetAwaiter().GetResult().
8489
}
90+
91+
private static void AddWorkingInfo(ServiceManagerBuilder builder, IConfiguration configuration)
92+
{
93+
var workerRuntime = configuration[Constants.FunctionsWorkerRuntime];
94+
if (workerRuntime != null)
95+
{
96+
builder.AddUserAgent($" [{Constants.FunctionsWorkerProductInfoKey}={workerRuntime}]");
97+
}
98+
}
8599
}
86100
}

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/tests/AzureSignalRClientTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public async Task GetClientConnectionInfo()
5353
[Fact]
5454
public async Task ServiceEndpointsNotSet()
5555
{
56-
var rootHubContextMock = new Mock<ServiceHubContext>().As<IInternalServiceHubContext>();
56+
var rootHubContextMock = new Mock<ServiceHubContext>();
5757
var childHubContextMock = new Mock<ServiceHubContext>();
5858
rootHubContextMock.Setup(c => c.WithEndpoints(It.IsAny<ServiceEndpoint[]>())).Returns(childHubContextMock.Object);
5959
rootHubContextMock.Setup(c => c.Clients.All.SendCoreAsync(It.IsAny<string>(), It.IsAny<object[]>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);
@@ -73,7 +73,7 @@ public async Task ServiceEndpointsNotSet()
7373
[Fact]
7474
public async Task ServiceEndpointsSet()
7575
{
76-
var rootHubContextMock = new Mock<ServiceHubContext>().As<IInternalServiceHubContext>();
76+
var rootHubContextMock = new Mock<ServiceHubContext>();
7777
var childHubContextMock = new Mock<ServiceHubContext>();
7878
rootHubContextMock.Setup(c => c.WithEndpoints(It.IsAny<ServiceEndpoint[]>())).Returns(childHubContextMock.Object);
7979
childHubContextMock.Setup(c => c.Clients.All.SendCoreAsync(It.IsAny<string>(), It.IsAny<object[]>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/tests/Config/ServiceManagerStoreTests.cs

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System.Collections.Generic;
55
using System.Linq;
6-
using System.Text.RegularExpressions;
76
using System.Threading.Tasks;
87
using Azure.Core.Serialization;
98
using Microsoft.Azure.SignalR;
@@ -16,26 +15,16 @@
1615
using Microsoft.Extensions.Configuration.Memory;
1716
using Microsoft.Extensions.DependencyInjection;
1817
using Microsoft.Extensions.Hosting;
19-
using Microsoft.Extensions.Logging;
2018
using Microsoft.Extensions.Logging.Abstractions;
2119
using Microsoft.Extensions.Options;
2220
using Moq;
23-
using SignalRServiceExtension.Tests.Utils.Loggings;
2421
using Xunit;
25-
using Xunit.Abstractions;
2622
using Constants = Microsoft.Azure.WebJobs.Extensions.SignalRService.Constants;
2723

2824
namespace SignalRServiceExtension.Tests
2925
{
3026
public class ServiceManagerStoreTests
3127
{
32-
private readonly ITestOutputHelper _output;
33-
34-
public ServiceManagerStoreTests(ITestOutputHelper output)
35-
{
36-
_output = output;
37-
}
38-
3928
[Fact]
4029
public void GetServiceManager_WithSingleEndpoint()
4130
{
@@ -58,14 +47,11 @@ public void ProductInfoValid()
5847
configuration[connectionStringKey] = connectionString;
5948
configuration[Constants.FunctionsWorkerRuntime] = Constants.DotnetWorker;
6049

61-
var setup = new OptionsSetup(configuration, SingletonAzureComponentFactory.Instance, connectionStringKey, new());
62-
var options = new ServiceManagerOptions();
63-
setup.Configure(options);
64-
Assert.NotNull(options.ProductInfo);
65-
var reg = new Regex(@"\[(\w*)=(\w*)\]");
66-
var match = reg.Match(options.ProductInfo);
67-
Assert.Equal(Constants.FunctionsWorkerProductInfoKey, match.Groups[1].Value);
68-
Assert.Equal(Constants.DotnetWorker, match.Groups[2].Value);
50+
var serviceManagerStore = new ServiceManagerStore(configuration, NullLoggerFactory.Instance, SingletonAzureComponentFactory.Instance, Options.Create(new SignalROptions()));
51+
var productInfo = (serviceManagerStore.GetOrAddByConnectionStringKey(connectionStringKey).GetAsync("hub").Result as ServiceHubContextImpl).ServiceProvider.GetRequiredService<IOptions<ServiceManagerOptions>>().Value.ProductInfo;
52+
Assert.NotNull(productInfo);
53+
Assert.StartsWith("Microsoft.Azure.WebJobs.Extensions.SignalRService", productInfo);
54+
Assert.EndsWith(" [func=dotnet]", productInfo);
6955
}
7056

7157
[Fact]
@@ -115,9 +101,7 @@ public async void TestConfigurationHotReload()
115101
configuration[Constants.AzureSignalRConnectionStringName] = connectionStrings[0];
116102
// Only persistent mode supports hot reload.
117103
configuration[Constants.ServiceTransportTypeName] = "Persistent";
118-
var loggerFactory = new LoggerFactory();
119-
loggerFactory.AddProvider(new XunitLoggerProvider(_output));
120-
var managerStore = new ServiceManagerStore(configuration, loggerFactory, SingletonAzureComponentFactory.Instance, Options.Create(new SignalROptions()), mock.Object);
104+
var managerStore = new ServiceManagerStore(configuration, NullLoggerFactory.Instance, SingletonAzureComponentFactory.Instance, Options.Create(new SignalROptions()), mock.Object);
121105
var hubContextStore = managerStore.GetOrAddByConnectionStringKey(Constants.AzureSignalRConnectionStringName);
122106
var hubContext = await hubContextStore.GetAsync("hub") as ServiceHubContext;
123107
await hubContext.ClientManager.UserExistsAsync("a");

0 commit comments

Comments
 (0)