An open API service indexing awesome lists of open source software.

https://github.com/dazinator/dazinator.extensions.configuration

Make implementing an IConfigurationProvider even easier.
https://github.com/dazinator/dazinator.extensions.configuration

Last synced: about 1 year ago
JSON representation

Make implementing an IConfigurationProvider even easier.

Awesome Lists containing this project

README

          

## Problem

This repository is home to a number of libraries that build upon `Microsoft.Extensions.Configuration` mainly an Async provider.

### Async

Implements all the boilder plate, and allows you to provide your own `asynchronous` configuration, with support for reloads in a simple way.
This library allows you to just to focus on providing the actual functionality you are interested in.

To use this library you just call `AddAsyncProvider` when building configuration. There are a couple of overloads:

Supply functions:

```csharp
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddAsyncProvider((source) =>
{
source.ChangeTokenProducer = () => EmptyChangeToken.Instance; // provide a change token, which when signalled will cause OnEnqueueReloadWorkItem to be invoked with a work item representing the async reload operation that must be performed.
source.OnLoadConfigurationAsync = LoadConfigurationAsync; // provide an async method to fetch the latest configuration from your store.
// When a reload change token is signalled, this method is called with a work item. Somewhere in your application (like in a backgrounnd service) you need to await this work item's Task - to actually perform the Reload operation.
// No reload will happen until you do this.
source.OnEnqueueReloadWorkItem = (reloadWorkItem) =>
{
queue.Enqueue(reloadWorkItem); // just adding to a queue, which you will dequeue and await in your application perhaps in a background service.
return true;
};
});

```

Or if you prefer to implement a class, you can supply an instance of `IAsyncConfigurationProvider`:

```csharp
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddAsyncProvider(new MyAsyncConfigurationProvider());
```

Where `MyAsyncConfigurationProvider` implements `IAsyncConfigurationProvider` and also optionally imlmenets `IDisposable`.

```csharp

public class MyAsyncConfigurationProvider : IAsyncConfigurationProvider, IDisposable
{
public void Dispose()
{
// you can optionally implement IDisposable interface
}

public IChangeToken GetReloadToken() => EmptyChangeToken.Instance;
public async Task> LoadAsync()
{
await Task.Yield();

var result = new Dictionary()
{
{ "key1", "value1" }
};
return result;
}
}
```

### Performing Reloads

`IChangeToken` is synchronous, yet we must perform `async` work to do a reload. So the actual async task representing the reload operation is pushed to you, as a "work item" for you to execut in your application.
This is so you can await and integrate the async reload operation cleanly into your application.
The recommended way to do this is creating your own `BackgroundService`
and using a simple queue, or `channel` you can enqueue this work item, then in the background service, dequeue and execute it.

```csharp
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddAsyncProvider((source) =>
{
source.OnEnqueueReloadWorkItem = (reloadWorkItem) =>
{
// Your queue implementation
YourQueueImplementation.Enqueue(reloadWorkItem); // just adding to a queue, which you will dequeue and await in your application perhaps in a background service.
return true;
};

```

```csharp

public class AsyncConfigurationReloadService : BackgroundService
{
private readonly YourQueueImplementation _queue;
private readonly ILogger _logger;

public AsyncConfigurationReloadService(YourQueueImplementation queue, ILogger logger)
{
_queue = queue;
_logger = logger;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// Await until the channel has work items to process or is completed
await foreach (var workItem in _queue.ReadAllAsync(stoppingToken))
{
// Process the async reload operation
await ProcessReload(workItem, stoppingToken);
}
}

private async Task ProcessReload(AsyncConfigReloadWorkItem workItem, CancellationToken stoppingToken)
{
try
{
// config will reload here
await workItem.GetReloadTask(stoppingToken);
}
catch (Exception e)
{
_logger.LogError("Unable to process config reload work item. {Exception}", e);
}
}
}
```

## Scaling

Because you are in control of factory that returns `IChangeToken`s used to signal async reloads, you can hook this in to any system you like.
So for example, you could use a `Redis` pub/sub system to signal reloads to multiple instances of your application.

## Additional Information

Async provider enabled me to build a Sql server provider:
Why a Sql server provider? https://gamma.app/docs/Custom-dotnet-configuration-provider-for-SQL-Server-with-realtime-ad56s549my9xtxq