HTTP polling provider for Cocoar.Configuration enabling remote configuration sources with configurable polling intervals, automatic retries, and failure sentinel values for resilient distributed configuration management.
$ dotnet add package Cocoar.Configuration.HttpPollingIReactiveConfig<T> (no extra setup)If you need more later (interface binding, DI lifetime control, custom providers) it’s all there—opt‑in, not in your face.
appsettings.json:
{
"App": {
"FeatureFlag": true,
"Message": "Hello from config"
}
}Program.cs:
var builder = WebApplication.CreateBuilder(args);
// Register layered configuration (file + environment overlay)
builder.Services.AddCocoarConfiguration([
Rule.From.File("appsettings.json").Select("App").For<AppSettings>(),
Rule.From.Environment("APP_").For<AppSettings>()
]);
var app = builder.Build();
// Simple endpoint: inject concrete snapshot (Scoped)
app.MapGet("/feature", (AppSettings cfg) => new {
snapshotFlag = cfg.FeatureFlag, // Value at scope start (request)
message = cfg.Message
});
// Reactive usage example (background logging)
var reactive = app.Services.GetRequiredService<IReactiveConfig<AppSettings>>();
var _ = reactive.Subscribe(c => Console.WriteLine($"[Config Updated] FeatureFlag={c.FeatureFlag}"));
app.Run();
public sealed class AppSettings
{
public bool FeatureFlag { get; set; }
public string Message { get; set; } = string.Empty;
}appsettings.json changed? — future requests see the updated snapshot; reactive stream subscribers get a push..
Every configuration type you map gets a free reactive companion:
| You Have | You Also Automatically Have |
|---|---|
AppSettings | IReactiveConfig<AppSettings> |
IReactiveConfig<T> gives you:
CurrentValue – latest stable valueSubscribe(...) – push updates only when actual content changesGuidance:
AppSettings) for a consistent snapshotIReactiveConfig<T>live.CurrentValue once (rarely required)A rule = provider + (optional selection/query) + target config type. Order matters: later rules overwrite earlier values per flattened key (deterministic last-write-wins).
var rules = new [] {
Rule.From.File("appsettings.json").For<AppSettings>(),
Rule.From.Environment("APP_").For<AppSettings>()
};Additional options (add only when needed):
Rule.From.File("secrets.json")
.Select("Secrets:Db") // select subtree
.Mount("Database") // mount under a new path
.Required() // fail the rule if source missing
.For<DatabaseConfig>();Start without it. Add when you want to inject contracts instead of concretes.
services.AddCocoarConfiguration(rules, [
Bind.Type<AppSettings>().To<IAppSettings>()
]);
public sealed class Handler(IAppSettings cfg, IReactiveConfig<IAppSettings> live)
{ /* ... */ }More patterns: BINDING.md.
By default:
IReactiveConfig<T>: Singleton (continuous live updates)Change the default lifetime:
services.AddCocoarConfiguration(rules, configureServices: o =>
o.DefaultRegistrationLifetime(ServiceLifetime.Singleton));Disable auto reactive registration (rare):
o.DisableAutoReactiveRegistration();Manual overrides & keyed registrations: see ADVANCED.md.
Choosing a Lifetime:
| Scenario | Lifetime |
|---|---|
| Typical web request consumption | Scoped |
| High-read immutable small config | Singleton |
| Background service (reactive) | Scoped + IReactiveConfig<T> (preferred) |
| Large object, avoid mid-request drift | Scoped |
| Provider | Package | Change Signal | Notes |
|---|---|---|---|
| Static | Core | ❌ | JSON strings or factories |
| File (JSON) | Core | ✅ FS watcher | Deterministic layering |
| Environment | Core | ❌ | Prefix filter; __ / : nesting |
| HTTP Polling | Extension | ✅ Interval polling | Payload diffing (streaming hash) |
| Microsoft Adapter | Extension | Depends | Any IConfigurationSource |
Detailed provider docs: PROVIDERS.md.
Deep dive: ARCHITECTURE.md, CONCEPTS.md.
| Need | Go To |
|---|---|
| Interface patterns | docs/BINDING.md |
| Advanced DI control | docs/ADVANCED.md |
| Architecture & pipeline | docs/ARCHITECTURE.md |
| Providers overview | docs/PROVIDERS.md |
| Migration notes | docs/MIGRATION.md |
| Build your own provider | docs/PROVIDER_DEV.md |
| Deep scenarios (lifecycle, dynamic factories, tuning) | docs/DEEP_DIVE.md |
<ItemGroup>
<PackageReference Include="Cocoar.Configuration" />
<PackageReference Include="Cocoar.Configuration.DI" />
<!-- Optional -->
<PackageReference Include="Cocoar.Configuration.HttpPolling" />
<PackageReference Include="Cocoar.Configuration.MicrosoftAdapter" />
<PackageReference Include="Cocoar.Configuration.AspNetCore" />
</ItemGroup>CLI:
dotnet add package Cocoar.Configuration
dotnet add package Cocoar.Configuration.DI(Add extensions only when needed.)
Each example is a standalone runnable project under src/Examples/:
| Project | Description |
|---|---|
| BasicUsage | Common ASP.NET Core pattern (file + env overlay) |
| FileLayering | Multiple JSON layering (base + env + local) |
| DynamicDependencies | Later rules derive values from earlier configs |
| AspNetCoreExample | Minimal API exposing config via endpoints |
| GenericProviderAPI | Generic provider registration API usage |
| HttpPollingExample | Remote HTTP polling configuration pattern |
| MicrosoftAdapterExample | Integrating existing IConfigurationSource assets |
| ServiceLifetimes | DI lifetime & keyed registration control |
| StaticProviderExample | Static seeding with JSON strings and factory functions |
| DIExample | Comprehensive DI patterns & overrides |
| SimplifiedCoreExample | Pure core (no DI) with ConfigManager |
| BindingExample | Interface binding without DI |
More details: Examples README.
This project is licensed under the Apache License, Version 2.0. See NOTICE for attribution.
"Cocoar" and related marks are trademarks of COCOAR e.U. Use of the name in forks or derivatives should preserve attribution and avoid implying official endorsement. See TRADEMARKS for permitted and restricted uses.