diff --git a/src/Core/Configurations/RuntimeConfigProvider.cs b/src/Core/Configurations/RuntimeConfigProvider.cs index 70327326ba..7c0364d4c1 100644 --- a/src/Core/Configurations/RuntimeConfigProvider.cs +++ b/src/Core/Configurations/RuntimeConfigProvider.cs @@ -25,7 +25,7 @@ namespace Azure.DataApiBuilder.Core.Configurations; /// should not load the config directly, or maintain a reference to it, so that we can do hot-reloading by replacing /// the config that is available from this type. /// -public class RuntimeConfigProvider +public class RuntimeConfigProvider : IDisposable { public delegate Task RuntimeConfigLoadedHandler(RuntimeConfigProvider sender, RuntimeConfig config); @@ -46,6 +46,7 @@ public class RuntimeConfigProvider private RuntimeConfigLoader _configLoader; private DabChangeToken _changeToken = new(); private readonly IDisposable _changeTokenRegistration; + private bool _disposed; public RuntimeConfigProvider(RuntimeConfigLoader runtimeConfigLoader) { @@ -89,6 +90,12 @@ public IChangeToken GetChangeToken() /// public void Dispose() { + if (_disposed) + { + return; + } + + _disposed = true; _changeTokenRegistration.Dispose(); } diff --git a/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs b/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs index 644bd338e3..9da39c14c6 100644 --- a/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs +++ b/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs @@ -80,7 +80,7 @@ public static async Task CreateWebHost( .AddEasyAuthAuthentication(easyAuthProvider); } - services.AddSingleton(runtimeConfigProvider); + services.AddSingleton(sp => runtimeConfigProvider); // https://github.com/dotnet/aspnetcore/issues/53332#issuecomment-2091861884 // AddRouting() adds required services that .NET8 does not add by default @@ -179,7 +179,7 @@ public static async Task CreateWebHostCustomIssuer(SecurityKey key) }; }); services.AddAuthorization(); - services.AddSingleton(runtimeConfigProvider); + services.AddSingleton(sp => runtimeConfigProvider); }) .ConfigureLogging(o => { diff --git a/src/Service.Tests/Authentication/JwtTokenAuthenticationUnitTests.cs b/src/Service.Tests/Authentication/JwtTokenAuthenticationUnitTests.cs index 789770c985..12a0b2ebd0 100644 --- a/src/Service.Tests/Authentication/JwtTokenAuthenticationUnitTests.cs +++ b/src/Service.Tests/Authentication/JwtTokenAuthenticationUnitTests.cs @@ -347,7 +347,7 @@ private static async Task CreateWebHostCustomIssuer(SecurityKey key) }; }); services.AddAuthorization(); - services.AddSingleton(runtimeConfigProvider); + services.AddSingleton(sp => runtimeConfigProvider); }) .ConfigureLogging(o => { diff --git a/src/Service.Tests/CosmosTests/TestBase.cs b/src/Service.Tests/CosmosTests/TestBase.cs index dfac601023..10f7a7bcd2 100644 --- a/src/Service.Tests/CosmosTests/TestBase.cs +++ b/src/Service.Tests/CosmosTests/TestBase.cs @@ -174,8 +174,8 @@ protected WebApplicationFactory SetupTestApplicationFactory() _ = builder.ConfigureTestServices(services => { services.AddSingleton(fileSystem); - services.AddSingleton(loader); - services.AddSingleton(provider); + services.AddSingleton(sp => loader); + services.AddSingleton(sp => provider); services.AddSingleton(authorizationResolverCosmos); }); }); diff --git a/src/Service.Tests/Mcp/AggregateRecordsToolTests.cs b/src/Service.Tests/Mcp/AggregateRecordsToolTests.cs index cb7514d45e..dd6587674c 100644 --- a/src/Service.Tests/Mcp/AggregateRecordsToolTests.cs +++ b/src/Service.Tests/Mcp/AggregateRecordsToolTests.cs @@ -665,7 +665,7 @@ private static IServiceProvider CreateServiceProvider(RuntimeConfig config) ServiceCollection services = new(); RuntimeConfigProvider configProvider = TestHelper.GenerateInMemoryRuntimeConfigProvider(config); - services.AddSingleton(configProvider); + services.AddSingleton(sp => configProvider); Mock mockAuthResolver = new(); mockAuthResolver.Setup(x => x.IsValidRoleContext(It.IsAny())).Returns(true); diff --git a/src/Service.Tests/Mcp/DescribeEntitiesFilteringTests.cs b/src/Service.Tests/Mcp/DescribeEntitiesFilteringTests.cs index 3defc34bba..68b9866760 100644 --- a/src/Service.Tests/Mcp/DescribeEntitiesFilteringTests.cs +++ b/src/Service.Tests/Mcp/DescribeEntitiesFilteringTests.cs @@ -457,7 +457,7 @@ private static IServiceProvider CreateServiceProvider(RuntimeConfig config) // Use shared test helper to create RuntimeConfigProvider RuntimeConfigProvider configProvider = TestHelper.GenerateInMemoryRuntimeConfigProvider(config); - services.AddSingleton(configProvider); + services.AddSingleton(sp => configProvider); // Mock IAuthorizationResolver Mock mockAuthResolver = new(); diff --git a/src/Service.Tests/Mcp/EntityLevelDmlToolConfigurationTests.cs b/src/Service.Tests/Mcp/EntityLevelDmlToolConfigurationTests.cs index aa3ae118dc..e0c43dbb2e 100644 --- a/src/Service.Tests/Mcp/EntityLevelDmlToolConfigurationTests.cs +++ b/src/Service.Tests/Mcp/EntityLevelDmlToolConfigurationTests.cs @@ -447,7 +447,7 @@ private static IServiceProvider CreateServiceProvider(RuntimeConfig config) ServiceCollection services = new(); RuntimeConfigProvider configProvider = TestHelper.GenerateInMemoryRuntimeConfigProvider(config); - services.AddSingleton(configProvider); + services.AddSingleton(sp => configProvider); Mock mockAuthResolver = new(); mockAuthResolver.Setup(x => x.IsValidRoleContext(It.IsAny())).Returns(true); diff --git a/src/Service.Tests/Mcp/McpQueryTimeoutTests.cs b/src/Service.Tests/Mcp/McpQueryTimeoutTests.cs index 835527865d..51a758c206 100644 --- a/src/Service.Tests/Mcp/McpQueryTimeoutTests.cs +++ b/src/Service.Tests/Mcp/McpQueryTimeoutTests.cs @@ -203,7 +203,7 @@ private static IServiceProvider CreateServiceProviderWithConfig(RuntimeConfig co { ServiceCollection services = new(); RuntimeConfigProvider configProvider = TestHelper.GenerateInMemoryRuntimeConfigProvider(config); - services.AddSingleton(configProvider); + services.AddSingleton(sp => configProvider); services.AddLogging(); return services.BuildServiceProvider(); } diff --git a/src/Service.Tests/SqlTests/SqlTestBase.cs b/src/Service.Tests/SqlTests/SqlTestBase.cs index 4e0fa5249c..f0bbd3258a 100644 --- a/src/Service.Tests/SqlTests/SqlTestBase.cs +++ b/src/Service.Tests/SqlTests/SqlTestBase.cs @@ -178,7 +178,7 @@ protected async static Task InitializeTestFixture( builder.ConfigureTestServices(services => { services.AddHttpContextAccessor(); - services.AddSingleton(runtimeConfigProvider); + services.AddSingleton(sp => runtimeConfigProvider); services.AddSingleton(_gqlFilterParser); services.AddSingleton(implementationFactory: serviceProvider => { diff --git a/src/Service/Startup.cs b/src/Service/Startup.cs index 618feef454..70c162a078 100644 --- a/src/Service/Startup.cs +++ b/src/Service/Startup.cs @@ -120,7 +120,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(fileSystem); services.AddSingleton(sp => configLoader); - services.AddSingleton(configProvider); + services.AddSingleton(sp => configProvider); bool runtimeConfigAvailable = configProvider.TryGetConfig(out RuntimeConfig? runtimeConfig);