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

Maintain Default Data Source Name from Original Config after Hot Reloading #2069

Merged
merged 23 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
899bd9d
pass in datasource to save in hot reload
aaronburtle Feb 28, 2024
7b1bfc4
add helper to update dictionaries in runtimeconfig
aaronburtle Feb 29, 2024
efd04ba
add testing, cleanup format
aaronburtle Mar 2, 2024
ecac30f
addressing comments, still need to remove GetDataSourceName()
aaronburtle Mar 11, 2024
2f57773
remove un-needed function for getting dataSourceName, cleanup test st…
aaronburtle Mar 11, 2024
58d418c
whitespace
aaronburtle Mar 11, 2024
732d32e
clarifying comments
aaronburtle Mar 12, 2024
81b2ecd
refactor update
aaronburtle Mar 12, 2024
b3c067b
use private DefaultDataSourceName
aaronburtle Mar 12, 2024
873445a
typos
aaronburtle Mar 12, 2024
1a9229d
push change to rivate
aaronburtle Mar 12, 2024
da0abcd
match mocked loader to new signature
aaronburtle Mar 12, 2024
f16ef6d
change get method to property
aaronburtle Mar 12, 2024
5e1b057
update references to property
aaronburtle Mar 12, 2024
579199f
add ignore for default data source name to unit test verifier
aaronburtle Mar 12, 2024
be78615
style fix
aaronburtle Mar 12, 2024
3d31d89
merging
aaronburtle Mar 12, 2024
7f316c3
merging main
aaronburtle Mar 12, 2024
9d1bd74
add ignore for other tests in verifier for Jsonignored DefaultDatasou…
aaronburtle Mar 12, 2024
f295edb
defensive coding, typo fix
aaronburtle Mar 12, 2024
5148832
format
aaronburtle Mar 13, 2024
be7bd5e
Merge branch 'main' into dev/aaronburtle/SaveDataSourceNameForHotReload
aaronburtle Mar 13, 2024
937b731
Merge branch 'main' into dev/aaronburtle/SaveDataSourceNameForHotReload
aaronburtle Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/Config/FileSystemRuntimeConfigLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ public bool TryLoadConfig(
{
if (!string.IsNullOrEmpty(dataSourceName))
{
config.UpdateDefaultDataSourceNameDependantDictionaries(dataSourceName);
config.DefaultDataSourceName = dataSourceName;
config.UpdateDefaultDataSourceName(dataSourceName);
}

return true;
Expand Down
39 changes: 25 additions & 14 deletions src/Config/ObjectModel/RuntimeConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ Runtime.GraphQL is null ||
}
}

[JsonIgnore]
aaronburtle marked this conversation as resolved.
Show resolved Hide resolved
public string DefaultDataSourceName;
public string _defaultDataSourceName;
aaronburtle marked this conversation as resolved.
Show resolved Hide resolved

private Dictionary<string, DataSource> _dataSourceNameToDataSource;

Expand Down Expand Up @@ -170,18 +169,18 @@ public RuntimeConfig(string? Schema, DataSource DataSource, RuntimeEntities Enti
this.DataSource = DataSource;
this.Runtime = Runtime;
this.Entities = Entities;
this.DefaultDataSourceName = Guid.NewGuid().ToString();
_defaultDataSourceName = Guid.NewGuid().ToString();

// we will set them up with default values
_dataSourceNameToDataSource = new Dictionary<string, DataSource>
{
{ DefaultDataSourceName, this.DataSource }
{ _defaultDataSourceName, this.DataSource }
};

_entityNameToDataSourceName = new Dictionary<string, string>();
foreach (KeyValuePair<string, Entity> entity in Entities)
{
_entityNameToDataSourceName.TryAdd(entity.Key, DefaultDataSourceName);
_entityNameToDataSourceName.TryAdd(entity.Key, _defaultDataSourceName);
}

// Process data source and entities information for each database in multiple database scenario.
Expand Down Expand Up @@ -242,7 +241,7 @@ public RuntimeConfig(string Schema, DataSource DataSource, RuntimeOptions Runtim
this.DataSource = DataSource;
this.Runtime = Runtime;
this.Entities = Entities;
this.DefaultDataSourceName = DefaultDataSourceName;
_defaultDataSourceName = DefaultDataSourceName;
_dataSourceNameToDataSource = DataSourceNameToDataSource;
_entityNameToDataSourceName = EntityNameToDataSourceName;
this.DataSourceFiles = DataSourceFiles;
Expand Down Expand Up @@ -277,24 +276,25 @@ public void UpdateDataSourceNameToDataSource(string dataSourceName, DataSource d
/// <summary>
/// In a Hot Reload scenario we should maintain the same default data source
/// name before the hot reload as after the hot reload. This is because we hold
/// references such as to the Data Source itself which depend on this data source name
/// references to the Data Source itself which depend on this data source name
/// for lookups. To correctly retrieve this information after a hot reload
/// we need the data source name to say the same after hot reloading. This method takes
/// we need the data source name to stay the same after hot reloading. This method takes
/// a default data source name, such as the one from before hot reload, and
/// replaces the current dictionary entries of this RuntimeConfig that were
/// built using a new, unique guid during the construction of this RuntimeConfig
/// with entries using the provided default data source name.
/// with entries using the provided default data source name. We then update the DefaultDataSourceName.
/// </summary>
/// <param name="defaultDataSourceName">The name used to update the dictionaries.</param>
public void UpdateDefaultDataSourceNameDependantDictionaries(string initialDefaultDataSourceName)
/// <param name="initialDefaultDataSourceName">The name used to update the dictionaries.</param>
public void UpdateDefaultDataSourceName(string initialDefaultDataSourceName)
{
_dataSourceNameToDataSource.Remove(DefaultDataSourceName);
_dataSourceNameToDataSource.Remove(_defaultDataSourceName);
_dataSourceNameToDataSource.Add(initialDefaultDataSourceName, this.DataSource);
aaronburtle marked this conversation as resolved.
Show resolved Hide resolved
foreach (KeyValuePair<string, Entity> entity in Entities)
{
_entityNameToDataSourceName.Remove(entity.Key);
_entityNameToDataSourceName.Add(entity.Key,initialDefaultDataSourceName);
_entityNameToDataSourceName[entity.Key] = initialDefaultDataSourceName;
}

_defaultDataSourceName = initialDefaultDataSourceName;
}

/// <summary>
Expand Down Expand Up @@ -327,6 +327,17 @@ public bool CheckDataSourceExists(string dataSourceName)
return _dataSourceNameToDataSource.ContainsKey(dataSourceName);
}

/// <summary>
/// Get the default datasource name.
/// </summary>
/// <returns>default datasourceName.</returns>
#pragma warning disable CA1024 // Use properties where appropriate. Reason: Do not want datasource serialized and want to keep it private to restrict set;
public string GetDefaultDataSourceName()
#pragma warning restore CA1024 // Use properties where appropriate
seantleonard marked this conversation as resolved.
Show resolved Hide resolved
{
return _defaultDataSourceName;
}

/// <summary>
/// Serializes the RuntimeConfig object to JSON for writing to file.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Config/RuntimeConfigLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static bool TryParseConfig(string json,
// set dataSourceName to default if not provided
if (string.IsNullOrEmpty(dataSourceName))
{
dataSourceName = config.DefaultDataSourceName;
dataSourceName = config.GetDefaultDataSourceName();
}

if (!string.IsNullOrEmpty(connectionString))
Expand Down Expand Up @@ -114,7 +114,7 @@ public static bool TryParseConfig(string json,
ds = ds with { ConnectionString = updatedConnection };
config.UpdateDataSourceNameToDataSource(dataSourceName, ds);

if (string.Equals(dataSourceKey, config.DefaultDataSourceName, StringComparison.OrdinalIgnoreCase))
if (string.Equals(dataSourceKey, config.GetDefaultDataSourceName(), StringComparison.OrdinalIgnoreCase))
{
config = config with { DataSource = ds };
}
Expand Down
12 changes: 6 additions & 6 deletions src/Core/Configurations/RuntimeConfigProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public bool TryGetLoadedConfig([NotNullWhen(true)] out RuntimeConfig? runtimeCon
public void HotReloadConfig()
{
// _runtimeconfig can not be null in a hot reload scenario
ConfigLoader.TryLoadKnownConfig(out _runtimeConfig, replaceEnvVar: true, _runtimeConfig!.DefaultDataSourceName);
ConfigLoader.TryLoadKnownConfig(out _runtimeConfig, replaceEnvVar: true, _runtimeConfig!.GetDefaultDataSourceName());
}

/// <summary>
Expand Down Expand Up @@ -194,7 +194,7 @@ public async Task<bool> Initialize(
_runtimeConfig = HandleCosmosNoSqlConfiguration(schema, _runtimeConfig, _runtimeConfig.DataSource.ConnectionString);
}

ManagedIdentityAccessToken[_runtimeConfig.DefaultDataSourceName] = accessToken;
ManagedIdentityAccessToken[_runtimeConfig.GetDefaultDataSourceName()] = accessToken;
}

bool configLoadSucceeded = await InvokeConfigLoadedHandlersAsync();
Expand Down Expand Up @@ -269,8 +269,8 @@ public async Task<bool> Initialize(
DatabaseType.CosmosDB_NoSQL => HandleCosmosNoSqlConfiguration(graphQLSchema, runtimeConfig, connectionString),
_ => runtimeConfig with { DataSource = runtimeConfig.DataSource with { ConnectionString = connectionString } }
};
ManagedIdentityAccessToken[_runtimeConfig.DefaultDataSourceName] = accessToken;
_runtimeConfig.UpdateDataSourceNameToDataSource(_runtimeConfig.DefaultDataSourceName, _runtimeConfig.DataSource);
ManagedIdentityAccessToken[_runtimeConfig.GetDefaultDataSourceName()] = accessToken;
_runtimeConfig.UpdateDataSourceNameToDataSource(_runtimeConfig.GetDefaultDataSourceName(), _runtimeConfig.DataSource);
seantleonard marked this conversation as resolved.
Show resolved Hide resolved

return await InvokeConfigLoadedHandlersAsync();
}
Expand Down Expand Up @@ -299,7 +299,7 @@ private static RuntimeConfig HandleCosmosNoSqlConfiguration(string? schema, Runt
{
if (string.IsNullOrEmpty(dataSourceName))
{
dataSourceName = runtimeConfig.DefaultDataSourceName;
dataSourceName = runtimeConfig.GetDefaultDataSourceName();
}

DbConnectionStringBuilder dbConnectionStringBuilder = new()
Expand Down Expand Up @@ -342,7 +342,7 @@ private static RuntimeConfig HandleCosmosNoSqlConfiguration(string? schema, Runt
// Update the connection string in the datasource with the one that was provided to the controller
dataSource = dataSource with { Options = options, ConnectionString = connectionString };

if (dataSourceName == runtimeConfig.DefaultDataSourceName)
if (dataSourceName == runtimeConfig.GetDefaultDataSourceName())
{
// update default db.
runtimeConfig = runtimeConfig with { DataSource = dataSource };
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Resolvers/MsSqlQueryExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public override async Task SetManagedIdentityAccessTokenIfAnyAsync(DbConnection
// using default datasource name for first db - maintaining backward compatibility for single db scenario.
if (string.IsNullOrEmpty(dataSourceName))
{
dataSourceName = ConfigProvider.GetConfig().DefaultDataSourceName;
dataSourceName = ConfigProvider.GetConfig().GetDefaultDataSourceName();
}

_dataSourceAccessTokenUsage.TryGetValue(dataSourceName, out bool setAccessToken);
Expand Down Expand Up @@ -198,7 +198,7 @@ public override string GetSessionParamsQuery(HttpContext? httpContext, IDictiona
{
if (string.IsNullOrEmpty(dataSourceName))
{
dataSourceName = ConfigProvider.GetConfig().DefaultDataSourceName;
dataSourceName = ConfigProvider.GetConfig().GetDefaultDataSourceName();
}

if (httpContext is null || !_dataSourceToSessionContextUsage[dataSourceName])
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Resolvers/MySqlQueryExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public override async Task SetManagedIdentityAccessTokenIfAnyAsync(DbConnection
// using default datasource name for first db - maintaining backward compatibility for single db scenario.
if (string.IsNullOrEmpty(dataSourceName))
{
dataSourceName = ConfigProvider.GetConfig().DefaultDataSourceName;
dataSourceName = ConfigProvider.GetConfig().GetDefaultDataSourceName();
}

_dataSourceAccessTokenUsage.TryGetValue(dataSourceName, out bool setAccessToken);
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Resolvers/PostgreSqlExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public override async Task SetManagedIdentityAccessTokenIfAnyAsync(DbConnection
// using default datasource name for first db - maintaining backward compatibility for single db scenario.
if (string.IsNullOrEmpty(dataSourceName))
{
dataSourceName = ConfigProvider.GetConfig().DefaultDataSourceName;
dataSourceName = ConfigProvider.GetConfig().GetDefaultDataSourceName();
}

_dataSourceAccessTokenUsage.TryGetValue(dataSourceName, out bool setAccessToken);
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Resolvers/QueryExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public QueryExecutor(DbExceptionParser dbExceptionParser,
{
if (string.IsNullOrEmpty(dataSourceName))
{
dataSourceName = ConfigProvider.GetConfig().DefaultDataSourceName;
dataSourceName = ConfigProvider.GetConfig().GetDefaultDataSourceName();
}

if (!ConnectionStringBuilders.ContainsKey(dataSourceName))
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Resolvers/SqlMutationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ await queryExecutor.ExecuteQueryAsync(
public async Task<IActionResult?> ExecuteAsync(RestRequestContext context)
{
// for REST API scenarios, use the default datasource
string dataSourceName = _runtimeConfigProvider.GetConfig().DefaultDataSourceName;
string dataSourceName = _runtimeConfigProvider.GetConfig().GetDefaultDataSourceName();

Dictionary<string, object?> parameters = PrepareParameters(context);
ISqlMetadataProvider sqlMetadataProvider = _sqlMetadataProviderFactory.GetMetadataProvider(dataSourceName);
Expand Down Expand Up @@ -1194,7 +1194,7 @@ private static TransactionScope ConstructTransactionScopeWithSpecifiedIsolationL
private string GetValidatedDataSourceName(string dataSourceName)
{
// For rest scenarios - no multiple db support. Hence to maintain backward compatibility, we will use the default db.
return string.IsNullOrEmpty(dataSourceName) ? _runtimeConfigProvider.GetConfig().DefaultDataSourceName : dataSourceName;
return string.IsNullOrEmpty(dataSourceName) ? _runtimeConfigProvider.GetConfig().GetDefaultDataSourceName() : dataSourceName;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Resolvers/SqlQueryEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ await ExecuteAsync(structure, dataSourceName),
public async Task<JsonDocument?> ExecuteAsync(FindRequestContext context)
{
// for REST API scenarios, use the default datasource
string dataSourceName = _runtimeConfigProvider.GetConfig().DefaultDataSourceName;
string dataSourceName = _runtimeConfigProvider.GetConfig().GetDefaultDataSourceName();

ISqlMetadataProvider sqlMetadataProvider = _sqlMetadataProviderFactory.GetMetadataProvider(dataSourceName);
SqlQueryStructure structure = new(
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Services/OpenAPI/OpenApiDocumentor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ private OpenApiPaths BuildPaths()
{
OpenApiPaths pathsCollection = new();

string defaultDataSourceName = _runtimeConfig.DefaultDataSourceName;
string defaultDataSourceName = _runtimeConfig.GetDefaultDataSourceName();
ISqlMetadataProvider metadataProvider = _metadataProviderFactory.GetMetadataProvider(defaultDataSourceName);
foreach (KeyValuePair<string, DatabaseObject> entityDbMetadataMap in metadataProvider.EntityToDatabaseObject)
{
Expand Down Expand Up @@ -952,7 +952,7 @@ private Dictionary<string, OpenApiSchema> CreateComponentSchemas()
Dictionary<string, OpenApiSchema> schemas = new();

// for rest scenario we need the default datasource name.
string defaultDataSourceName = _runtimeConfig.DefaultDataSourceName;
string defaultDataSourceName = _runtimeConfig.GetDefaultDataSourceName();
ISqlMetadataProvider metadataProvider = _metadataProviderFactory.GetMetadataProvider(defaultDataSourceName);

foreach (KeyValuePair<string, DatabaseObject> entityDbMetadataMap in metadataProvider.EntityToDatabaseObject)
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Services/RestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ RequestValidator requestValidator
private async Task<IActionResult> DispatchQuery(RestRequestContext context, DatabaseType databaseType)
{
IQueryEngine queryEngine = _queryEngineFactory.GetQueryEngine(databaseType);
string defaultDataSourceName = _runtimeConfigProvider.GetConfig().DefaultDataSourceName;
string defaultDataSourceName = _runtimeConfigProvider.GetConfig().GetDefaultDataSourceName();

if (context is FindRequestContext findRequestContext)
{
Expand All @@ -237,7 +237,7 @@ private async Task<IActionResult> DispatchQuery(RestRequestContext context, Data
private Task<IActionResult?> DispatchMutation(RestRequestContext context, DatabaseType databaseType)
{
IMutationEngine mutationEngine = _mutationEngineFactory.GetMutationEngine(databaseType);
string defaultDataSourceName = _runtimeConfigProvider.GetConfig().DefaultDataSourceName;
string defaultDataSourceName = _runtimeConfigProvider.GetConfig().GetDefaultDataSourceName();
return context switch
{
StoredProcedureRequestContext => mutationEngine.ExecuteAsync((StoredProcedureRequestContext)context, defaultDataSourceName),
Expand Down Expand Up @@ -437,7 +437,7 @@ public bool TryGetRestRouteFromConfig([NotNullWhen(true)] out string? configured
public (string, string) GetEntityNameAndPrimaryKeyRouteFromRoute(string routeAfterPathBase)
{

string dataSourceName = _runtimeConfigProvider.GetConfig().DefaultDataSourceName;
string dataSourceName = _runtimeConfigProvider.GetConfig().GetDefaultDataSourceName();
ISqlMetadataProvider sqlMetadataProvider = _sqlMetadataProviderFactory.GetMetadataProvider(dataSourceName);

// Split routeAfterPath on the first occurrence of '/', if we get back 2 elements
Expand Down
2 changes: 1 addition & 1 deletion src/Service.Tests/Authorization/AuthorizationHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static AuthorizationResolver InitAuthorizationResolver(RuntimeConfig runt
metadataProvider.Setup(x => x.GetEntityName(It.IsAny<string>()))
.Returns((string entity) => entity);
Mock<IMetadataProviderFactory> metadataProviderFactory = new();
string dataSourceName = runtimeConfigProvider.GetConfig().DefaultDataSourceName;
string dataSourceName = runtimeConfigProvider.GetConfig().GetDefaultDataSourceName();
metadataProviderFactory.Setup(x => x.GetMetadataProvider(dataSourceName)).Returns(metadataProvider.Object);

return new AuthorizationResolver(runtimeConfigProvider, metadataProviderFactory.Object);
Expand Down
4 changes: 2 additions & 2 deletions src/Service.Tests/CosmosTests/CosmosClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class CosmosClientTests : TestBase
public void CosmosClientDefaultUserAgent()
{
CosmosClientProvider cosmosClientProvider = _application.Services.GetService<CosmosClientProvider>();
CosmosClient client = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().DefaultDataSourceName];
CosmosClient client = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().GetDefaultDataSourceName()];
// Validate results
Assert.AreEqual(client.ClientOptions.ApplicationName, ProductInfo.DEFAULT_APP_NAME);
}
Expand All @@ -33,7 +33,7 @@ public void CosmosClientEnvUserAgent()
WebApplicationFactory<Startup> application = SetupTestApplicationFactory();

CosmosClientProvider cosmosClientProvider = application.Services.GetService<CosmosClientProvider>();
CosmosClient client = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().DefaultDataSourceName];
CosmosClient client = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().GetDefaultDataSourceName()];
// Validate results
Assert.AreEqual(client.ClientOptions.ApplicationName, appName);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Service.Tests/CosmosTests/MutationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class MutationTests : TestBase
public void TestFixtureSetup()
{
CosmosClientProvider cosmosClientProvider = _application.Services.GetService<CosmosClientProvider>();
CosmosClient cosmosClient = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().DefaultDataSourceName];
CosmosClient cosmosClient = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().GetDefaultDataSourceName()];
cosmosClient.CreateDatabaseIfNotExistsAsync(DATABASE_NAME).Wait();
cosmosClient.GetDatabase(DATABASE_NAME).CreateContainerIfNotExistsAsync(_containerName, "/id").Wait();
CreateItems(DATABASE_NAME, _containerName, 10);
Expand Down Expand Up @@ -740,7 +740,7 @@ type Planet @model(name:""Planet"") {
public void TestFixtureTearDown()
{
CosmosClientProvider cosmosClientProvider = _application.Services.GetService<CosmosClientProvider>();
CosmosClient cosmosClient = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().DefaultDataSourceName];
CosmosClient cosmosClient = cosmosClientProvider.Clients[cosmosClientProvider.RuntimeConfigProvider.GetConfig().GetDefaultDataSourceName()];
cosmosClient.GetDatabase(DATABASE_NAME).GetContainer(_containerName).DeleteContainerAsync().Wait();
}
}
Expand Down
Loading