diff --git a/src/Config/FileSystemRuntimeConfigLoader.cs b/src/Config/FileSystemRuntimeConfigLoader.cs index f9cd9f4ffe..cbe357c835 100644 --- a/src/Config/FileSystemRuntimeConfigLoader.cs +++ b/src/Config/FileSystemRuntimeConfigLoader.cs @@ -156,11 +156,6 @@ public bool TryLoadConfig( logger?.LogInformation("Monitoring config: {ConfigFilePath} for hot-reloading.", ConfigFilePath); } - if (!string.IsNullOrEmpty(defaultDataSourceName)) - { - RuntimeConfig.DefaultDataSourceName = defaultDataSourceName; - } - config = RuntimeConfig; return true; } diff --git a/src/Config/HotReloadEventHandler.cs b/src/Config/HotReloadEventHandler.cs index 885192f2ac..74a1872e46 100644 --- a/src/Config/HotReloadEventHandler.cs +++ b/src/Config/HotReloadEventHandler.cs @@ -22,14 +22,13 @@ public HotReloadEventHandler() { _eventHandlers = new Dictionary?> { + // QueryManagerFactory will create a new set of QueryExecutors + // during Hot-Reload so it is not necessary to specifically reconfigure + // QueryExecutors as part of the Hot-Reload process. { QUERY_MANAGER_FACTORY_ON_CONFIG_CHANGED, null }, { METADATA_PROVIDER_FACTORY_ON_CONFIG_CHANGED, null }, { QUERY_ENGINE_FACTORY_ON_CONFIG_CHANGED,null }, { MUTATION_ENGINE_FACTORY_ON_CONFIG_CHANGED,null }, - { QUERY_EXECUTOR_ON_CONFIG_CHANGED, null }, - { MSSQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, null }, - { MYSQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, null }, - { POSTGRESQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, null }, { DOCUMENTOR_ON_CONFIG_CHANGED, null } }; } diff --git a/src/Config/ObjectModel/RuntimeConfig.cs b/src/Config/ObjectModel/RuntimeConfig.cs index 5bec0bf209..eefb0dcbdc 100644 --- a/src/Config/ObjectModel/RuntimeConfig.cs +++ b/src/Config/ObjectModel/RuntimeConfig.cs @@ -178,7 +178,12 @@ public bool TryGetEntityNameFromPath(string entityPathName, [NotNullWhen(true)] /// Runtime settings. /// List of datasource files for multiple db scenario. Null for single db scenario. [JsonConstructor] - public RuntimeConfig(string? Schema, DataSource DataSource, RuntimeEntities Entities, RuntimeOptions? Runtime = null, DataSourceFiles? DataSourceFiles = null) + public RuntimeConfig( + string? Schema, + DataSource DataSource, + RuntimeEntities Entities, + RuntimeOptions? Runtime = null, + DataSourceFiles? DataSourceFiles = null) { this.Schema = Schema ?? DEFAULT_CONFIG_SCHEMA_LINK; this.DataSource = DataSource; @@ -189,13 +194,13 @@ public RuntimeConfig(string? Schema, DataSource DataSource, RuntimeEntities Enti // we will set them up with default values _dataSourceNameToDataSource = new Dictionary { - { DefaultDataSourceName, this.DataSource } + { this.DefaultDataSourceName, this.DataSource } }; _entityNameToDataSourceName = new Dictionary(); foreach (KeyValuePair entity in Entities) { - _entityNameToDataSourceName.TryAdd(entity.Key, DefaultDataSourceName); + _entityNameToDataSourceName.TryAdd(entity.Key, this.DefaultDataSourceName); } // Process data source and entities information for each database in multiple database scenario. diff --git a/src/Config/RuntimeConfigLoader.cs b/src/Config/RuntimeConfigLoader.cs index fda5dc3b16..e30b3c9f46 100644 --- a/src/Config/RuntimeConfigLoader.cs +++ b/src/Config/RuntimeConfigLoader.cs @@ -56,10 +56,6 @@ protected void SendEventNotification(string message = "") OnConfigChangedEvent(new HotReloadEventArgs(METADATA_PROVIDER_FACTORY_ON_CONFIG_CHANGED, message)); OnConfigChangedEvent(new HotReloadEventArgs(QUERY_ENGINE_FACTORY_ON_CONFIG_CHANGED, message)); OnConfigChangedEvent(new HotReloadEventArgs(MUTATION_ENGINE_FACTORY_ON_CONFIG_CHANGED, message)); - OnConfigChangedEvent(new HotReloadEventArgs(QUERY_EXECUTOR_ON_CONFIG_CHANGED, message)); - OnConfigChangedEvent(new HotReloadEventArgs(MSSQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, message)); - OnConfigChangedEvent(new HotReloadEventArgs(MYSQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, message)); - OnConfigChangedEvent(new HotReloadEventArgs(POSTGRESQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, message)); OnConfigChangedEvent(new HotReloadEventArgs(DOCUMENTOR_ON_CONFIG_CHANGED, message)); } @@ -97,7 +93,6 @@ public static bool TryParseConfig(string json, ILogger? logger = null, string? connectionString = null, bool replaceEnvVar = false, - string dataSourceName = "", Dictionary? datasourceNameToConnectionString = null, EnvironmentVariableReplacementFailureMode replacementFailureMode = EnvironmentVariableReplacementFailureMode.Throw) { @@ -115,12 +110,6 @@ public static bool TryParseConfig(string json, // retreive current connection string from config string updatedConnectionString = config.DataSource.ConnectionString; - // set dataSourceName to default if not provided - if (string.IsNullOrEmpty(dataSourceName)) - { - dataSourceName = config.DefaultDataSourceName; - } - if (!string.IsNullOrEmpty(connectionString)) { // update connection string if provided. @@ -133,7 +122,7 @@ public static bool TryParseConfig(string json, } // add to dictionary if datasourceName is present (will either be the default or the one provided) - datasourceNameToConnectionString.TryAdd(dataSourceName, updatedConnectionString); + datasourceNameToConnectionString.TryAdd(config.DefaultDataSourceName, updatedConnectionString); // iterate over dictionary and update runtime config with connection strings. foreach ((string dataSourceKey, string connectionValue) in datasourceNameToConnectionString) @@ -153,7 +142,7 @@ public static bool TryParseConfig(string json, } ds = ds with { ConnectionString = updatedConnection }; - config.UpdateDataSourceNameToDataSource(dataSourceName, ds); + config.UpdateDataSourceNameToDataSource(config.DefaultDataSourceName, ds); if (string.Equals(dataSourceKey, config.DefaultDataSourceName, StringComparison.OrdinalIgnoreCase)) { diff --git a/src/Core/Resolvers/MsSqlQueryExecutor.cs b/src/Core/Resolvers/MsSqlQueryExecutor.cs index 3097e53dd0..43a9132b32 100644 --- a/src/Core/Resolvers/MsSqlQueryExecutor.cs +++ b/src/Core/Resolvers/MsSqlQueryExecutor.cs @@ -16,7 +16,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.Data.SqlClient; using Microsoft.Extensions.Logging; -using static Azure.DataApiBuilder.Config.DabConfigEvents; namespace Azure.DataApiBuilder.Core.Resolvers { @@ -77,7 +76,6 @@ public MsSqlQueryExecutor( httpContextAccessor, handler) { - handler?.Subscribe(MSSQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, OnConfigChanged); _dataSourceAccessTokenUsage = new Dictionary(); _dataSourceToSessionContextUsage = new Dictionary(); _accessTokensFromConfiguration = runtimeConfigProvider.ManagedIdentityAccessToken; @@ -109,19 +107,6 @@ private void ConfigureMsSqlQueryEecutor() } } - /// - /// Function registered for callback during a hot-reload scenario. - /// - /// The calling object. - /// Event arguments. - public void MsSqlQueryExecutorOnConfigChanged(object? sender, HotReloadEventArgs args) - { - _dataSourceAccessTokenUsage = new Dictionary(); - _dataSourceToSessionContextUsage = new Dictionary(); - _accessTokensFromConfiguration = _runtimeConfigProvider.ManagedIdentityAccessToken; - ConfigureMsSqlQueryEecutor(); - } - /// /// Modifies the properties of the supplied connection to support managed identity access. /// In the case of MsSql, gets access token if deemed necessary and sets it on the connection. diff --git a/src/Core/Resolvers/MySqlQueryExecutor.cs b/src/Core/Resolvers/MySqlQueryExecutor.cs index 3925a37fc3..b28620b09a 100644 --- a/src/Core/Resolvers/MySqlQueryExecutor.cs +++ b/src/Core/Resolvers/MySqlQueryExecutor.cs @@ -11,7 +11,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using MySqlConnector; -using static Azure.DataApiBuilder.Config.DabConfigEvents; namespace Azure.DataApiBuilder.Core.Resolvers { @@ -67,7 +66,6 @@ public MySqlQueryExecutor( httpContextAccessor, handler) { - handler?.Subscribe(MYSQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, MySqlQueryExecutorOnConfigChanged); _dataSourceAccessTokenUsage = new Dictionary(); _accessTokensFromConfiguration = runtimeConfigProvider.ManagedIdentityAccessToken; _runtimeConfigProvider = runtimeConfigProvider; @@ -100,18 +98,6 @@ private void ConfigureMySqlQueryExecutor() } } - /// - /// Function registered for callback during a hot-reload scenario. - /// - /// The calling object. - /// Event arguments. - public void MySqlQueryExecutorOnConfigChanged(object? sender, HotReloadEventArgs args) - { - _dataSourceAccessTokenUsage = new Dictionary(); - _accessTokensFromConfiguration = _runtimeConfigProvider.ManagedIdentityAccessToken; - ConfigureMySqlQueryExecutor(); - } - /// /// Modifies the properties of the supplied connection to support managed identity access. /// In the case of MySql, gets access token if deemed necessary and sets it on the connection. diff --git a/src/Core/Resolvers/PostgreSqlExecutor.cs b/src/Core/Resolvers/PostgreSqlExecutor.cs index 219ff9b8de..9bab1f8a39 100644 --- a/src/Core/Resolvers/PostgreSqlExecutor.cs +++ b/src/Core/Resolvers/PostgreSqlExecutor.cs @@ -11,7 +11,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Npgsql; -using static Azure.DataApiBuilder.Config.DabConfigEvents; namespace Azure.DataApiBuilder.Core.Resolvers { @@ -68,7 +67,6 @@ public PostgreSqlQueryExecutor( httpContextAccessor, handler) { - handler?.Subscribe(POSTGRESQL_QUERY_EXECUTOR_ON_CONFIG_CHANGED, PostgreSqlQueryExecutorOnConfigChanged); _dataSourceAccessTokenUsage = new Dictionary(); _accessTokensFromConfiguration = runtimeConfigProvider.ManagedIdentityAccessToken; _runtimeConfigProvider = runtimeConfigProvider; @@ -97,18 +95,6 @@ private void ConfigurePostgreSqlQueryExecutor() } } - /// - /// Function registered for callback during a hot-reload scenario. - /// - /// The calling object. - /// Event arguments. - public void PostgreSqlQueryExecutorOnConfigChanged(object? sender, HotReloadEventArgs args) - { - _dataSourceAccessTokenUsage = new Dictionary(); - _accessTokensFromConfiguration = _runtimeConfigProvider.ManagedIdentityAccessToken; - ConfigurePostgreSqlQueryExecutor(); - } - /// /// Modifies the properties of the supplied connection string to support managed identity access. /// In the case of Postgres, if a default managed identity needs to be used, the password in the diff --git a/src/Core/Resolvers/QueryExecutor.cs b/src/Core/Resolvers/QueryExecutor.cs index 743f0e8141..52d33637d6 100644 --- a/src/Core/Resolvers/QueryExecutor.cs +++ b/src/Core/Resolvers/QueryExecutor.cs @@ -16,7 +16,6 @@ using Microsoft.Extensions.Logging; using Polly; using Polly.Retry; -using static Azure.DataApiBuilder.Config.DabConfigEvents; namespace Azure.DataApiBuilder.Core.Resolvers { @@ -56,7 +55,6 @@ public QueryExecutor(DbExceptionParser dbExceptionParser, IHttpContextAccessor httpContextAccessor, HotReloadEventHandler? handler) { - handler?.Subscribe(QUERY_EXECUTOR_ON_CONFIG_CHANGED, OnConfigChanged); DbExceptionParser = dbExceptionParser; QueryExecutorLogger = logger; ConnectionStringBuilders = new Dictionary(); @@ -86,18 +84,6 @@ public QueryExecutor(DbExceptionParser dbExceptionParser, }); } - /// - /// Function registered for callback during a hot-reload scenario. - /// - /// The calling object. - /// Event arguments. - public void OnConfigChanged(object? sender, HotReloadEventArgs args) - { - ConnectionStringBuilders = new Dictionary(); - _maxResponseSizeMB = ConfigProvider.GetConfig().MaxResponseSizeMB(); - _maxResponseSizeBytes = _maxResponseSizeMB * 1024 * 1024; - } - /// public virtual TResult? ExecuteQuery( string sqltext, diff --git a/src/Core/Services/MetadataProviders/MetadataProviderFactory.cs b/src/Core/Services/MetadataProviders/MetadataProviderFactory.cs index bd268a6fdb..e58c44955f 100644 --- a/src/Core/Services/MetadataProviders/MetadataProviderFactory.cs +++ b/src/Core/Services/MetadataProviders/MetadataProviderFactory.cs @@ -17,7 +17,7 @@ namespace Azure.DataApiBuilder.Core.Services.MetadataProviders /// public class MetadataProviderFactory : IMetadataProviderFactory { - private readonly IDictionary _metadataProviders; + private IDictionary _metadataProviders; private readonly RuntimeConfigProvider _runtimeConfigProvider; private readonly IAbstractQueryManagerFactory _queryManagerFactory; private readonly ILogger _logger; @@ -62,7 +62,10 @@ private void ConfigureMetadataProviders() public void OnConfigChanged(object? sender, HotReloadEventArgs args) { + _metadataProviders = new Dictionary(); ConfigureMetadataProviders(); + // Blocks the current thread until initialization is finished. + this.InitializeAsync().GetAwaiter().GetResult(); } ///