Goldpath.Campaign
0.1.0-preview.8
dotnet add package Goldpath.Campaign --version 0.1.0-preview.8
NuGet\Install-Package Goldpath.Campaign -Version 0.1.0-preview.8
<PackageReference Include="Goldpath.Campaign" Version="0.1.0-preview.8" />
<PackageVersion Include="Goldpath.Campaign" Version="0.1.0-preview.8" />
<PackageReference Include="Goldpath.Campaign" />
paket add Goldpath.Campaign --version 0.1.0-preview.8
#r "nuget: Goldpath.Campaign, 0.1.0-preview.8"
#:package Goldpath.Campaign@0.1.0-preview.8
#addin nuget:?package=Goldpath.Campaign&version=0.1.0-preview.8&prerelease
#tool nuget:?package=Goldpath.Campaign&version=0.1.0-preview.8&prerelease
Goldpath.Campaign
Governed mass-execution — L4 of the execution ladder, the top rung. A campaign is a durable plan: targets are enumerated ahead into rows, then RELEASED to competing broker consumers at a pace the operator governs live:
create → enumerate (streaming, ceilinged) → release under policy → consumers execute
│ │ │
│ watermark checkpoint │ TPS / daily quota / │ claim-before-
│ (takeover-safe) │ window / max-in-flight │ execute, then
│ │ (all LIVE-adjustable) │ publish outcome
└── ceiling hit → PAUSED └── single leader, └── batching sink
(a decision, not a default) in-memory ticks writes truth
The pacer is a LONG-LIVED leader run on Goldpath.Jobs: the ~1-minute cron only guarantees a leader exists; pacing happens on in-memory ticks (250ms default) against durable watermarks — leader death means the next fire takes over from the row, mid-campaign.
Wire it
builder.AddGoldpathCampaign<WebApplicationBuilder, OrdersDbContext>(campaign =>
{
campaign.AddCampaign<DormantCustomer>("winback", c => c
.MaxTargets(2_000_000) // MANDATORY — unbounded L4 is an outage
.Targets((services, parameters) => services.GetRequiredService<OrdersDbContext>()
.Customers.Where(x => x.LastOrderAt < DateTime.Parse(parameters["before"]))
.OrderBy(x => x.Id) // stable order — the watermark depends on it
.Select(x => new DormantCustomer(x.Id, x.Email))
.AsAsyncEnumerable())
.DefaultPolicy(p => p with { Tps = 100, DailyQuota = 500_000, MaxInFlight = 2_000 }));
});
builder.Services.AddScoped<IGoldpathCampaignItemHandler<DormantCustomer>, WinbackHandler>();
builder.AddGoldpathJobs<WebApplicationBuilder, OrdersDbContext>(jobs =>
{
jobs.ConnectionName = "ordersdb";
jobs.AddGoldpathCampaignJobs<OrdersDbContext>(); // the pacer leader
});
builder.AddGoldpathMessaging<WebApplicationBuilder>(bus => // campaign REQUIRES a broker
{
bus.AddGoldpathCampaignConsumers<OrdersDbContext>();
});
// DbContext: modelBuilder.AddGoldpathCampaign(); modelBuilder.AddGoldpathJobs();
The guarantees
- The ceiling is mandatory: a type without
MaxTargetsrefuses to bake (GP1701); an enumeration that exceeds it PAUSES the campaign for a human decision. - Policy is live: TPS, daily quota, send window (timezone-aware, overnight windows supported) and max-in-flight are row values the pacer re-reads every tick — a throttle takes effect within one tick, no restart, no redeploy.
- Double-send is structurally impossible: the consumer CLAIMS the item row (state-guarded update) before the handler's external call; a broker redelivery claims zero rows and drops. Claimed-but-unstamped items are swept to the repair queue — confirm with the provider, then replay; never silently re-send.
- 30M items never mean 30M writes: outcomes are published, batched by the sink, and flushed as set-based updates; enumeration and release are batched the same way.
- Repair, not requeue: every failed item lands in the jobs repair queue with its
coordinate (
{campaign}#{seq});replay-itemsre-executes through your handler. - Takeover-safe: enumeration and release advance durable watermarks; a new leader resumes exactly where the dead one stopped.
Ops surface (create/pause/resume/abort/throttle admin API, per-campaign panel, runbooks) ships in S2; run views live in the JOBS console today — the pacer IS a jobs run.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Goldpath.Abstractions (>= 0.1.0-preview.8)
- Goldpath.Data (>= 0.1.0-preview.8)
- Goldpath.Jobs (>= 0.1.0-preview.8)
- Goldpath.Messaging (>= 0.1.0-preview.8)
- Goldpath.Sdk (>= 0.1.0-preview.8)
-
net8.0
- Goldpath.Abstractions (>= 0.1.0-preview.8)
- Goldpath.Data (>= 0.1.0-preview.8)
- Goldpath.Jobs (>= 0.1.0-preview.8)
- Goldpath.Messaging (>= 0.1.0-preview.8)
- Goldpath.Sdk (>= 0.1.0-preview.8)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-preview.8 | 58 | 9/7/2026 |
| 0.1.0-preview.7 | 64 | 9/1/2026 |
| 0.1.0-preview.6 | 77 | 8/4/2026 |
| 0.1.0-preview.5 | 71 | 7/28/2026 |
| 0.1.0-preview.4 | 64 | 7/27/2026 |
| 0.1.0-preview.3 | 63 | 7/25/2026 |
| 0.1.0-preview.2 | 74 | 7/13/2026 |
| 0.1.0-preview.1 | 83 | 7/13/2026 |