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 | ❌ | Seed defaults, compose values |
| 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 + dependent recompute |
| DIExample | Comprehensive DI patterns & overrides |
| SimplifiedCoreExample | Pure core (no DI) with ConfigManager |
| BindingExample | Interface binding without DI |
More details: Examples README.