Azure / Azure/AppConfiguration-DotnetProvider

Support custom IConfigurationRefresher implementations in AzureAppConfigurationRefresherProvider

Open
#713 18 comments 1 reaction 1 assignee Claimed by @zhiyuanliang-ms View on GitHub
Dominant language
C#
Stars
93
Forks
46
Avg merge
3d 1h
Merged PRs (30d)
3

Description

Hi!

We're trying to add Azure App Configuration sources with a priority lower than the default `appsettings.{Environment}.json` file's one, using `WebApplicationBuilder`.

We noticed that `WebApplicationBuilder`'s behavior is to trigger a reload of all sources in `Configuration.Sources` every time the collection is modified in any way other than with `Add` (e.g., with `Insert`).

Loading the configuration from AAC more than once is problematic as it can take a lot of time, especially when some configuration keys link to Azure Key Vaults. Doing this work several times impacts negatively the startup time of an application that uses `WebApplicationBuilder`.

We already opened an [issue](https://github.com/dotnet/runtime/issues/123188) about this behavior in the ASP.NET Core repo, but we thought that in the meantime, we could shield the Azure App Configuration source/provider from those reloads by registering our one decorator implementation of `IConfigurationSource`/`IConfigurationProvider`/`IConfigurationRefresher`.

However, as soon as we try to use AAC's dynamic configuration middleware (with `UseAzureAppConfiguration`), we get an `InvalidOperationException` from this [code](https://github.com/Azure/AppConfiguration-DotnetProvider/blob/34576ef70d303a029b7ea7ef860f12885fb8f35d/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationRefresherProvider.cs#L52-L55):

```csharp
if (!refreshers.Any())
{
throw new InvalidOperationException("Unable to access the Azure App Configuration provider. Please ensure that it has been configured correctly.");
}
```

Despite the interfaces being public, the method `FindRefreshers` of [`AzureAppConfigurationRefresherProvider`](https://github.com/Azure/AppConfiguration-DotnetProvider/blob/34576ef70d303a029b7ea7ef860f12885fb8f35d/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationRefresherProvider.cs) still expects the implementation of all `configurationRoot.Providers` to be of the `AzureAppConfigurationProvider` internal type (probably to be able to set the logger factory via the `LoggerFactory` property, which is not part of the [`IConfigurationRefresher`](https://github.com/Azure/AppConfiguration-DotnetProvider/blob/34576ef70d303a029b7ea7ef860f12885fb8f35d/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/IConfigurationRefresher.cs) interface).

```csharp
if (provider is AzureAppConfigurationProvider appConfigurationProvider)
{
appConfigurationProvider.LoggerFactory = loggerFactory;
refreshers.Add(appConfigurationProvider);
}
```

This prevents us to use `AzureAppConfigurationRefresherProvider` with our own implementation of `IConfigurationProvider`/`IConfigurationRefresher`.

We could implement our own `IConfigurationRefresherProvider` (and thus duplicate the logic of `AzureAppConfigurationRefresherProvider`) in order to support our other custom implementations, but it is not ideal.

Would it be possible to stop locking `AzureAppConfigurationRefresherProvider` to a specific implementation of `IConfigurationRefresher` (possibly by promoting the `LoggerFactory` property to the `IConfigurationRefresher` interface)?

Thanks a lot for your consideration.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.