{"id":17078496,"url":"https://github.com/dazinator/dazinator.extensions.configuration","last_synced_at":"2025-06-15T12:07:42.921Z","repository":{"id":174398225,"uuid":"651897372","full_name":"dazinator/Dazinator.Extensions.Configuration","owner":"dazinator","description":"Make implementing an IConfigurationProvider even easier.","archived":false,"fork":false,"pushed_at":"2024-04-13T15:29:27.000Z","size":92,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-06-11T08:31:37.441Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dazinator.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-06-10T12:32:59.000Z","updated_at":"2024-01-12T19:53:50.000Z","dependencies_parsed_at":"2024-04-16T03:43:27.484Z","dependency_job_id":null,"html_url":"https://github.com/dazinator/Dazinator.Extensions.Configuration","commit_stats":{"total_commits":25,"total_committers":2,"mean_commits":12.5,"dds":"0.040000000000000036","last_synced_commit":"ba94297596f8f2dd050e930cfadce21dd2cf55ce"},"previous_names":["dazinator/dazinator.extensions.configuration"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dazinator/Dazinator.Extensions.Configuration","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.Extensions.Configuration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.Extensions.Configuration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.Extensions.Configuration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.Extensions.Configuration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dazinator","download_url":"https://codeload.github.com/dazinator/Dazinator.Extensions.Configuration/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dazinator%2FDazinator.Extensions.Configuration/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259971379,"owners_count":22940012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T12:22:17.098Z","updated_at":"2025-06-15T12:07:42.900Z","avatar_url":"https://github.com/dazinator.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Problem\n\nThis repository is home to a number of libraries that build upon `Microsoft.Extensions.Configuration` mainly an Async provider.\n\n### Async\n\nImplements all the boilder plate, and allows you to provide your own `asynchronous` configuration, with support for reloads in a simple way.\nThis library allows you to just to focus on providing the actual functionality you are interested in.\n\nTo use this library you just call `AddAsyncProvider` when building configuration. There are a couple of overloads:\n\nSupply functions:\n\n```csharp\n  var configurationBuilder = new ConfigurationBuilder();\n        configurationBuilder.AddAsyncProvider((source) =\u003e\n        {\n            source.ChangeTokenProducer = () =\u003e 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.\n            source.OnLoadConfigurationAsync = LoadConfigurationAsync; // provide an async method to fetch the latest configuration from your store.\n            // 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.\n            // No reload will happen until you do this.   \n            source.OnEnqueueReloadWorkItem = (reloadWorkItem) =\u003e\n            {\n                queue.Enqueue(reloadWorkItem); // just adding to a queue, which you will dequeue and await in your application perhaps in a background service.\n                return true;\n            };\n        });\n\n```\n\nOr if you prefer to implement a class, you can supply an instance of `IAsyncConfigurationProvider`:\n\n```csharp\n  var configurationBuilder = new ConfigurationBuilder();\n\t\tconfigurationBuilder.AddAsyncProvider(new MyAsyncConfigurationProvider());\n```\n\nWhere `MyAsyncConfigurationProvider` implements `IAsyncConfigurationProvider` and also optionally imlmenets `IDisposable`.\n\n```csharp\n\n    public class MyAsyncConfigurationProvider : IAsyncConfigurationProvider, IDisposable\n    {\n        public void Dispose()\n        {\n            // you can optionally implement IDisposable interface\n        }\n\n        public IChangeToken GetReloadToken() =\u003e EmptyChangeToken.Instance;\n        public async Task\u003cIDictionary\u003cstring, string\u003e\u003e LoadAsync()\n        {\n            await Task.Yield();\n\n            var result = new Dictionary\u003cstring, string\u003e()\n            {\n                { \"key1\", \"value1\" }\n            };\n            return result;\n        }\n    }\n```\n\n### Performing Reloads\n\n`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.\nThis is so you can await and integrate the async reload operation cleanly into your application. \nThe recommended way to do this is creating your own `BackgroundService`\nand using a simple queue, or `channel` you can enqueue this work item, then in the background service, dequeue and execute it.\n\n```csharp\nvar configurationBuilder = new ConfigurationBuilder();\n        configurationBuilder.AddAsyncProvider((source) =\u003e\n        {\n            source.OnEnqueueReloadWorkItem = (reloadWorkItem) =\u003e\n            {\n                // Your queue implementation\n                YourQueueImplementation.Enqueue(reloadWorkItem); // just adding to a queue, which you will dequeue and await in your application perhaps in a background service.\n                return true;\n            };\n\n```\n\n```csharp\n\npublic class AsyncConfigurationReloadService : BackgroundService\n{\n    private readonly YourQueueImplementation\u003cAsyncConfigReloadWorkItem\u003e _queue;\n    private readonly ILogger\u003cAsyncConfigurationReloadService\u003e _logger;\n\n    public AsyncConfigurationReloadService(YourQueueImplementation\u003cAsyncConfigReloadWorkItem\u003e queue, ILogger\u003cAsyncConfigurationReloadService\u003e logger)\n    {\n        _queue = queue;\n        _logger = logger;     \n    }\n\n    protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n    {\n        // Await until the channel has work items to process or is completed\n        await foreach (var workItem in _queue.ReadAllAsync(stoppingToken))\n        {\n            // Process the async reload operation\n            await ProcessReload(workItem, stoppingToken);\n        }\n    }\n\n    private async Task ProcessReload(AsyncConfigReloadWorkItem workItem, CancellationToken stoppingToken)\n    {\n        try\n        {\n            // config will reload here\n            await workItem.GetReloadTask(stoppingToken);\n        }\n        catch (Exception e)\n        {\n            _logger.LogError(\"Unable to process config reload work item. {Exception}\", e);\n        }\n    }\n}\n```\n\n## Scaling\n\nBecause 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. \nSo for example, you could use a `Redis` pub/sub system to signal reloads to multiple instances of your application.\n\n## Additional Information\n\nAsync provider enabled me to build a Sql server provider:\nWhy a Sql server provider? https://gamma.app/docs/Custom-dotnet-configuration-provider-for-SQL-Server-with-realtime-ad56s549my9xtxq\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdazinator%2Fdazinator.extensions.configuration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdazinator%2Fdazinator.extensions.configuration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdazinator%2Fdazinator.extensions.configuration/lists"}