in src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs [159:202]
public override void Load()
{
var watch = Stopwatch.StartNew();
using Activity activity = _activitySource.StartActivity(ActivityNames.Load);
try
{
using var startupCancellationTokenSource = new CancellationTokenSource(_options.Startup.Timeout);
// Load() is invoked only once during application startup. We don't need to check for concurrent network
// operations here because there can't be any other startup or refresh operation in progress at this time.
LoadAsync(_optional, startupCancellationTokenSource.Token).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (ArgumentException)
{
// Instantly re-throw the exception
throw;
}
catch
{
// AzureAppConfigurationProvider.Load() method is called in the application's startup code path.
// Unhandled exceptions cause application crash which can result in crash loops as orchestrators attempt to restart the application.
// Knowing the intended usage of the provider in startup code path, we mitigate back-to-back crash loops from overloading the server with requests by waiting a minimum time to propogate fatal errors.
var waitInterval = MinDelayForUnhandledFailure.Subtract(watch.Elapsed);
if (waitInterval.Ticks > 0)
{
Task.Delay(waitInterval).ConfigureAwait(false).GetAwaiter().GetResult();
}
// Re-throw the exception after the additional delay (if required)
throw;
}
finally
{
// Set the provider for AzureAppConfigurationRefresher instance after LoadAll has completed.
// This stops applications from calling RefreshAsync until config has been initialized during startup.
var refresher = (AzureAppConfigurationRefresher)_options.GetRefresher();
refresher.SetProvider(this);
}
// Mark all settings have loaded at startup.
_isInitialLoadComplete = true;
}