-
Notifications
You must be signed in to change notification settings - Fork 103
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
Set up options and track changes in management SDK. #1081
Conversation
src/Microsoft.Azure.SignalR.Management/Configuration/ServiceManagerContextSetup.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/Configuration/ServiceManagerContextSetup.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/DependencyInjectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/DependencyInjectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/ServiceManagerBuilder.cs
Outdated
Show resolved
Hide resolved
7c4dbf7
to
e889b03
Compare
src/Microsoft.Azure.SignalR.Management/Microsoft.Azure.SignalR.Management.csproj
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/ServiceManagerBuilder.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/DependencyInjectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/ServiceManagerBuilder.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/ServiceManagerBuilder.cs
Outdated
Show resolved
Hide resolved
2802b44
to
a9b7d1b
Compare
src/Microsoft.Azure.SignalR.Management/Configuration/CascadeOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/Configuration/CascadeOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/Configuration/ServiceOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/DependencyInjectionExtensions.cs
Outdated
Show resolved
Hide resolved
test/Microsoft.Azure.SignalR.Management.Tests/DiExtensionFacts.cs
Outdated
Show resolved
Hide resolved
…erviceManagerOptions is configured.
…, change hot reload unit tests
177ce85
to
80874da
Compare
src/Microsoft.Azure.SignalR.Management/ServiceManagerBuilder.cs
Outdated
Show resolved
Hide resolved
_options.ValidateOptions(); | ||
|
||
_services.AddSignalRServiceManagerCore(); | ||
_serviceProvider = _services.BuildServiceProvider(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if Build
is called twice? the first _serviceProvider
never dispose?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check added, throw InvalidOperationException() if called twice.
src/Microsoft.Azure.SignalR.Management/ServiceManagerBuilder.cs
Outdated
Show resolved
Hide resolved
@@ -9,6 +9,7 @@ internal static class Constants | |||
{ | |||
public static class Keys | |||
{ | |||
public const string ServiceManagerOptionsSectionKey = "Azure:SignalR"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use a more common name if it is in Common project, or you can move the const to the Management project
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move the key to ServiceManagerOptions
as a const string named Section
.
src/Microsoft.Azure.SignalR.Management/Configuration/ServiceManagerContextSetup.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/Configuration/ServiceOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Azure.SignalR.Management/ServiceManagerBuilder.cs
Outdated
Show resolved
Hide resolved
…s; try to resolve conflict of config file name
internal abstract class CascadeOptionsSetup<TargetOptions> : IConfigureOptions<TargetOptions>, IOptionsChangeTokenSource<TargetOptions> | ||
where TargetOptions : class | ||
{ | ||
private readonly ServiceManagerOptions _initialSource; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what needs to be hot-reloaded is the multiple endpoint configure? So is it that we only need to track ServiceManagerOptions
=> ServiceOptions
change? Does it work if ServiceManagerContext
inherits ServiceOptions
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good idea.
/// <summary> | ||
/// The section name used to get <see cref="ServiceManagerOptions"/> value from <see cref="IConfiguration.GetSection(string)"/> | ||
/// </summary> | ||
public const string Section = "Azure:SignalR"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
intended to expose it to customer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think customer can get the right position of configuration from Section
.
_options.ValidateOptions(); | ||
if (ServiceProvider != null) | ||
{ | ||
throw new InvalidOperationException($"Mulitple invocation of the method is not allowed."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why we have such restriction is because we want UT to test ServiceProvider
? otherwise ServiceProvider
can be disposed inside Build()
?
Should the following case be a valid one?
var manager1 = builder.WithOptions(o=>o.ConnectionString="one").Build();
var manager2 = builder.WithOptions(o=>o.ConnectionString="another").Build();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ServiceProvider
is disposed, then all the services built by service provider are disposed. We should only dispose ServiceProvider
only when we don't need ServiceManager
anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now ServiceProvider
is disposed from ServiceManager
…ken : ServiceOptions => ServiceManagerContext => ServiceManagerOptions
… for ServiceManagerBuilder.
… service collection.
{ | ||
if (_configuration != null) | ||
{ | ||
_configuration.GetSection(Constants.Keys.AzureSignalRSectionKey).Bind(options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think adding services.Configure<ServiceManagerOptions>(Configuration.GetSection(Constants.Keys.AzureSignalRSectionKey));
is enough, we don't need this setup class as we don't have additional setups? Emulator uses such configure and hotreload works, see https://github.com/Azure/azure-signalr/blob/dev/src/Microsoft.Azure.SignalR.Emulator/Startup.cs#L45
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In here, https://github.com/Azure/azure-signalr/blob/dev/src/Microsoft.Azure.SignalR.Emulator/Startup.cs#L45, the Configuration
variable is actually an IConfiguration
type variable. However, in the extension methods of ServiceCollection
, we don't have IConfiguration
. Do you think we should add it as a parameter?
|
||
private static IServiceCollection TrySetProductInfo(this IServiceCollection services) | ||
{ | ||
var assembly = Assembly.GetExecutingAssembly(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this anyway executes even if ProductInfo
is already set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but if ProductInfo
is not null, then the value would not be overwritten.
|
||
internal ServiceManager(ServiceManagerContext context, RestClientFactory restClientFactory) | ||
//in builder mode, serviceProvider is not null and should be disposed. | ||
internal ServiceManager(ServiceManagerContext context, RestClientFactory restClientFactory, ServiceProvider serviceProvider = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when would ServiceProvider
be null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, some mistakes here . Changed it to IServiceProvider
from ServiceProvider
and make it required .
where TargetOptions : class | ||
{ | ||
private ConfigurationReloadToken _changeToken; | ||
private IDisposable _registration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
readonly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix
|
||
public string Name => Options.DefaultName; | ||
|
||
public void Configure(TargetOptions target) => Convert(target, _sourceOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is using sourceMonitor.CurrentValue
better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
@@ -141,6 +144,14 @@ public async Task<IServiceHubContext> CreateHubContextAsync(string hubName, ILog | |||
} | |||
} | |||
|
|||
public void Dispose() | |||
{ | |||
if (_context.DisposeServiceProvider) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is passing some ownServiceProvider
parameter in .ctor doable?
… remove null defalut value.
_services.AddSignalRServiceManager(); | ||
_services.Configure<ServiceManagerContext>(c => c.DisposeServiceProvider = true); | ||
var serviceProvider = _services.BuildServiceProvider(); | ||
var context = serviceProvider.GetRequiredService<IOptions<ServiceManagerContext>>().Value; | ||
var productInfo = ProductInfo.GetProductInfo(_assembly); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
read from context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Summary of the changes
ServiceManagerContext
to trackServiceManagerOptions
, set upServiceOptions
to trackServiceManagerContext
Configuration Methods
DI style
Method1: use configuration instance such as JSON file and so on. It's OK that no configuration file is found.
Method2: use delegate and configuration file.
ServiceManagerBuilder