{"id":19443058,"url":"https://github.com/asizikov/dynamic-config","last_synced_at":"2026-05-08T13:07:22.370Z","repository":{"id":141789787,"uuid":"255286965","full_name":"asizikov/dynamic-config","owner":"asizikov","description":"PoC project. DynamicConfig.Configuration library aims to provide an abstraction over the configuration management system. It provides the 'hot' settings reload without a need to redeploy or restart an application.","archived":false,"fork":false,"pushed_at":"2024-10-22T15:06:48.000Z","size":1379,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-07T22:13:27.345Z","etag":null,"topics":["asp-net-core","configuration-management","docker-compose","redis"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asizikov.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"publiccode":null,"codemeta":null}},"created_at":"2020-04-13T09:45:15.000Z","updated_at":"2024-10-22T15:08:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"981a3567-a2d8-4a7f-8c12-cc55293cf97c","html_url":"https://github.com/asizikov/dynamic-config","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asizikov%2Fdynamic-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asizikov%2Fdynamic-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asizikov%2Fdynamic-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asizikov%2Fdynamic-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asizikov","download_url":"https://codeload.github.com/asizikov/dynamic-config/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240627961,"owners_count":19831599,"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":["asp-net-core","configuration-management","docker-compose","redis"],"created_at":"2024-11-10T15:41:53.779Z","updated_at":"2026-05-08T13:07:17.314Z","avatar_url":"https://github.com/asizikov.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"dynamic-config\n====\n\n[![⚙️ Build Application](https://github.com/asizikov/dynamic-config/actions/workflows/build-application.yml/badge.svg)](https://github.com/asizikov/dynamic-config/actions/workflows/build-application.yml)\n\n### Project overview \n\n`DynamicConfig.Configuration` library aims to provide an abstraction over the configuration management system. It provides the 'hot' settings reload without a need to redeploy or restart an application.\n\nThis repository consists of a few packages: \n\n* `DynamicConfig.Configuration` is a client library which manages a local cache of settings for the given service\n* `DynamicConfig.Storage.Api` is a .NET Core Web API project which provides an http interface for the Configuration lib. It seres and up-to-date configuration state stored in a central redis db.\n* `DynamicConfig.Management.Web` is a configuration management portal, which provides standard CRUD operations to the settings set.\n* `clients/DatabasePrimer.Service` a side-car service for the `DynamicConfig.Management.Web` project. It's only goal is to insert some configs, to solve the cold start problem. (for the demo purpose it just inserts some random keys/values to the db)\n* `clients/WorkerService.ServiceA` is an example client application with is using the `DynamicConfig.Configuration` lib to keep its settings up to date.\n\n### How to build/test\n\nMake sure you have .NET Core 8.0 SDK installed.\n\nNavigate to the repo root and run: \n\n```\ndotnet build\ndotnet test\n```\n\nand enjoy :)\n\n### How to see it in action\n\nMake sure you have Docker installed.\n\nNavigate to the repo root and run: \n\n```\ndocker-compose build\ndocker-compose up (-d)\n```\n\nthis will bring up the following system: \n\n\n![](docs/images/docker-compose-overview.jpg)\n\nThere will be two networks spined up :`internal` and `public`.\n\nIn a private network you will find three services: \n\n1. `dynamic-config-redis-storage` a Redis service\n2. `dynamic-config-management-web` a management portal which enables you to perform CRUD operations on your settings set.\n3. `dynamic-config-database-primer` a service which seeds an initial data and randomly adds keys to DB\n\nIn a public network you have following services available: \n\n4. `dynamic-config-storage-api` a read-only api which provides clients with an up-to-date configuration. Could be scaled individually depends on the load. \n5. `client-service-a` a service which uses a `DynamicConfig.Configuration` library to access it's settings.\n\nthe management portal should be available on : \n\n`http://0.0.0.0:8081`\n\nMake sure to take a look at logs (either run `docker compose up` without `-d` key, or log in to a container and check it's logs (`docker ps` `docker logs`), or use you Docker Desktop UI tool, whatever floats your boat.). You will notice how the DatabasePrimer puts new settings key to the DB, how ServiceA tries to refresh its settings and how Storage.Api services an updated keys set.\n\n\n### Library overview\n\nTo use the library make sure to have it linked to your project (as a NuGet package, one day, maybe, or just as a project reference for now).\n\nin a `Startup.cs` or whatever is the right place to configure the DI composition root for your project type use: \n\n```c#\nservices.UseDynamicConfiguration(Configuration);\n```\nwhere `Configuration` is your `IConfiguration` instance.\n\nThis will register `IConfigurationReader` as a singleton in your DI container and kick off the synchronization process.\n\nIf you're going to use the library this way you'd need to have following env vars provider (well, they don't have to be ENVVARS, but they have to be discoverable through the .NET Core configuration system via `IConfiguration` interface implementation): \n\n```bash\nDYNAMIC_CONFIG_APPLICATION_NAME=SERVICE-A\nDYNAMIC_CONFIG_REFRESH_INTERVAL_MS=10000\nDYNAMIC_CONFIG_STORAGE_CONNECTION_STRING=http://dynamic-config-storage-api:80\n\n```\n\nalternatively you can manually create an instance of `ConfigurationReader` by providing these values as a constructor parameters: \n\n```c#\nnew ConfigurationReader(\"service-a\", \"http://connection:123\", 1000);\n```\n\nThen, whenever you need an access to the config you can inject the `IConfigurationReader` and use it like that: \n\n```c#\nvar value = _configurationReader.GetValue\u003cstring\u003e(\"SiteName\");\n```\n\nthis will return an up-to-date settings value. Keep in mind that this will be either the very fresh value (if the sync process has succeeded recently, or it will fallback to you `appsettings.json` value (or any other source depends on the config provider configured for your app and accessible via `IConfiguration`)\n\n\n#### Library architecture overview\n\n![](docs/images/lib-overview.jpeg)\n\nThe library consists of three components. \n\n* Settings Reader: a public interface, providing an access to the existing SettingsCache\n* SettingsCache an immutable key-value collection of known active keys for this application.\n* Configuration Updater Job: a background process which periodically polls a Storage API, processed the response and swaps the SettingsCache with a new one (remember, the cache is immutable)\n\n#### Storage structure\n\nRedis entries managed by this application have the following structure: \n\n![](docs/images/redis-known-keys.png)\n\nA json payload with the list of 'known configurations'. This is used by the Management portal UI. Retrieved and stored as a whole.\n\n![](docs/images/redis-service-keys.png)\n\nSettings list per service (`service-a` on the screenshot). Stored as a hash because it's managed by .NET Core `IDistributedCache` implementations.\n\n### Q\u0026A\n\n\u003e Why the odd code style? \n\nNo practical reason, tbh. It's just a good indicator that the settings set from my `.editorconfig` was picked up by the IDE and code format action has been applied to the file. \n\n\u003e Why so few tests?\n\nThe library it tested, but other systems are not covered very well, simply because I didn't have enough time.\n\n\u003e Why just Redis? \n\nThis is probably not the best solution, because it makes key management a bit cumbersome. I should have split the storage into two parts: a bit more advanced storage like CosmosDB/MongoDB/MSSQL and a settings cache in Redis organized by application name.\n\nThis will allow us to have a nice table-like persisted storage, where we can perform CRURD operations. This storage won't be very loaded, because it'll be isolated from all the polling by clients.\n\nAnd if we add a sync service with would detect storage modification (it could be notified by the message on the message bus), which would take care of Redis cache update (remove inactive settings, insert new settings, update existing active settings).\n\nBut that's probably too much for a weekend PoC project, right?\n\n\u003e Why there is no 'Create new' or 'Edit' ui and implementation in the Management portal?\n\nSame reason as above. Not enough time.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasizikov%2Fdynamic-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasizikov%2Fdynamic-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasizikov%2Fdynamic-config/lists"}