-
Notifications
You must be signed in to change notification settings - Fork 184
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
Hot Reload Validation #2405
base: main
Are you sure you want to change the base?
Hot Reload Validation #2405
Conversation
…piDoc' into dev/rubencerna/HotReload_Validation
IFileSystem fileSystem = new FileSystem(); | ||
ILoggerFactory loggerFactory = new LoggerFactory(); | ||
ILogger<RuntimeConfigValidator> logger = loggerFactory.CreateLogger<RuntimeConfigValidator>(); | ||
RuntimeConfigValidator runtimeConfigValidator = new(this, fileSystem, logger, true); |
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.
Not sure if this is fine, since there is no logger inside the provider
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.
For now, this is the only straightforward way of achieving validation during a hot reload.
My original response was the following, however we need to re-evaluate how we configure services in startup.cs such that we don't need to have runtimeconfigprovider resolved. That will need to be tracked via a separate task.
--------------------Obsolete-----------------------
There looks to be a better way of accomplishing instantiation of the RuntimeConfigValidator
.
In Startup.cs:
IFileSystem fileSystem = new FileSystem();
FileSystemRuntimeConfigLoader configLoader = new(fileSystem, hotReloadEventHandler, configFileName, connectionString);
RuntimeConfigProvider configProvider = new(configLoader);
RuntimeConfigValidator configValidator = new(
runtimeConfigProvider: configProvider,
fileSystem: fileSystem,
logger: , // this is an issue, we can't resolve an ilogger in Startup::ConfigureServices
isValidateOnly: true);
services.AddSingleton(fileSystem);
services.AddSingleton(configProvider);
services.AddSingleton(configLoader);
services.AddSingleton<configValidator>(); // instead of "services.AddSingleton<RuntimeConfigValidator>();"
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 was not able to find the code you put from Startup.cs and that way of instantiating RuntimeConfigValidator
did not work for me.
/azp run |
Pull request contains merge conflicts. |
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.
You should add a little more detail to your PR description describing how these mechanisms work:
- Hot Reload occurs which updates state in the Loader -> NewConfigDetected, isNewConfigValidated, "used"/newRuntimeConfigObject
- any service which attempts to
RuntimeConfigProvider::GetRuntimeConfig()
will triggerRuntimeConfigProvider::GetRuntimeConfig()
's internal logic to check the loaders state for isnewconfigValidated, and attempt to validate the config. then return the validated config.
Then describe what the expectations should be when a hotreloadedconfig is invalid.
Another thing to think about: - do we need to introduce a lock in
RuntimeConfigProvider::GetRuntimeConfig()
if the condition holds that the new runtimeconfig needs validation? e.g. if multiple dependent services attempt to fetch a hotreloaded config, only only operation should trigger validation, and the remaining callers can utilize that result as opposed to trigger multiple validation operations on the same config.
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.
- Updated the description
- I changed it so that
FileSystemRuntimeConfig::HotReloadConfig()
is the one that changes the state of isNewConfigValidated and isNewConfigDetected, so I believe that the internal logic to validate the config will only happen when there is a hot reload.
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.
- The changes I made, make it so that it only makes the validation on the first
OnConfigChangeEvent
while the others use the result.
/azp run |
/azp run |
1 similar comment
/azp run |
_configLoader.isNewConfigValidated = true; | ||
_configLoader.RuntimeConfig = _configLoader.lastValidRuntimeConfig; | ||
|
||
throw new DataApiBuilderException( | ||
message: "Failed validation of configuration file.", | ||
statusCode: HttpStatusCode.ServiceUnavailable, | ||
subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); |
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.
Because you're reverting to a Last Known Good (LKG) runtimeconfig
where isNewConfigValidated
is true:
- Do you still need to raise an exception?
- What would catch that exception and would such an exception imply that DAB should shut down?
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 still think that we should raise an exception that allows the user to know that their changes to the hot reload were not successful and that they are using their old configuration settings. As for the exception, it is catched in ConfigFileWatcher::OnConfigFileChange
which from my understanding, implies that DAB should still be running, and it gives a chance to the user to correctly change their config file for hot reload.
|
||
public bool isNewConfigDetected; | ||
|
||
public bool isNewConfigValidated = true; |
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.
Should this default to false? only switch to true when validated?
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, isNewConfigDetected
is by default false and should only switch to true when there is going to be a hot-reload
_configLoader.isNewConfigValidated = true; | ||
_configLoader.RuntimeConfig = _configLoader.lastValidRuntimeConfig; |
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.
perhaps this should be a function internal to the ConfigLoader so that ConfigLoader handles its own state whenever possible versus the Provider doing it, What do you think of this?
_configLoader.RestoreLkgConfig()
-> internally restores loader.lastValidConfig to loader.Config
IFileSystem fileSystem = new FileSystem(); | ||
ILoggerFactory loggerFactory = new LoggerFactory(); | ||
ILogger<RuntimeConfigValidator> logger = loggerFactory.CreateLogger<RuntimeConfigValidator>(); | ||
RuntimeConfigValidator runtimeConfigValidator = new(this, fileSystem, logger, true); |
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.
For now, this is the only straightforward way of achieving validation during a hot reload.
My original response was the following, however we need to re-evaluate how we configure services in startup.cs such that we don't need to have runtimeconfigprovider resolved. That will need to be tracked via a separate task.
--------------------Obsolete-----------------------
There looks to be a better way of accomplishing instantiation of the RuntimeConfigValidator
.
In Startup.cs:
IFileSystem fileSystem = new FileSystem();
FileSystemRuntimeConfigLoader configLoader = new(fileSystem, hotReloadEventHandler, configFileName, connectionString);
RuntimeConfigProvider configProvider = new(configLoader);
RuntimeConfigValidator configValidator = new(
runtimeConfigProvider: configProvider,
fileSystem: fileSystem,
logger: , // this is an issue, we can't resolve an ilogger in Startup::ConfigureServices
isValidateOnly: true);
services.AddSingleton(fileSystem);
services.AddSingleton(configProvider);
services.AddSingleton(configLoader);
services.AddSingleton<configValidator>(); // instead of "services.AddSingleton<RuntimeConfigValidator>();"
@@ -74,6 +76,34 @@ public RuntimeConfigProvider(RuntimeConfigLoader runtimeConfigLoader) | |||
/// <exception cref="DataApiBuilderException">Thrown when the loader is unable to load an instance of the config from its known location.</exception> | |||
public RuntimeConfig GetConfig() | |||
{ | |||
// Only used in hot reload to validate the configuration file | |||
if (_configLoader.isNewConfigDetected && !_configLoader.isNewConfigValidated) |
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.
your pr description checks the box for "integration tests." how do existing integration tests check hot reload and this new functionality? I'd suggest outline in your PR description how you tested this, even if manually tested.
message: "Failed validation of configuration file.", | ||
statusCode: HttpStatusCode.ServiceUnavailable, | ||
subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); | ||
} |
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.
how have we tested this? Is there a way to add an automated integration test in ConfigurationTests.cs?
@@ -31,6 +31,12 @@ public abstract class RuntimeConfigLoader | |||
// state in place of using out params. | |||
public RuntimeConfig? RuntimeConfig; | |||
|
|||
public RuntimeConfig? lastValidRuntimeConfig; |
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.
All these properties are public properties. So, naming convention wise they should be capitalized. LastValidRuntimeConfig, IsNewConfigDetected, IsNewConfigValidated.
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.
Waiting for testing.
Why make this change?
This change fixes issue #2396
What is this change?
In order to validate the hot-reload, first, new logic was added to the
RuntimeConfigLoader
andFileSystemRuntimeConfigLoader
, so when hot reload occurs, it updates the new states added to the loader which are isNewConfigDetected, isNewConfigValidated, and lastValidRuntimeConfig.Once the states are updated, it will try to parse and validate the new RuntimeConfig, in the case that it fails at any step of the way, the hot-reloading process will be canceled and the RuntimeConfig file will be changed so that it uses the information from lastValidRuntimeConfig so that the user can still use their last configuration without any problems.
How was this tested?