HostLoom.Leadership 0.17.0

dotnet add package HostLoom.Leadership --version 0.17.0
                    
NuGet\Install-Package HostLoom.Leadership -Version 0.17.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HostLoom.Leadership" Version="0.17.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="HostLoom.Leadership" Version="0.17.0" />
                    
Directory.Packages.props
<PackageReference Include="HostLoom.Leadership" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add HostLoom.Leadership --version 0.17.0
                    
#r "nuget: HostLoom.Leadership, 0.17.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package HostLoom.Leadership@0.17.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=HostLoom.Leadership&version=0.17.0
                    
Install as a Cake Addin
#tool nuget:?package=HostLoom.Leadership&version=0.17.0
                    
Install as a Cake Tool

HostLoom.Leadership

HostLoom.Leadership elects one leader for a role among the instances of a service, over the HostLoom distributed lock. It is the lease-based election that Kubernetes controllers, Spring Integration's leader initiator, and most cloud services use: a candidate tries to take the lease leader:{role} by default, the leader renews it on its own cadence, and a renewal the backend refuses or a lease that runs out steps the instance back to candidate at once. A renewal that fails at the provider while the lease still runs keeps leadership and the term: the leader retries, at the renewal cadence or at half the remaining lease when that is sooner, until an extension succeeds or the lease ends. The package references HostLoom.Locking and Microsoft.Extensions.Logging.Abstractions; every type has a public constructor, so an elector composes without a container.

var elector = new LeaderElector("billing", locks, new LeadershipOptions());
await elector.StartAsync();

await elector.WaitForLeadershipAsync(stoppingToken);
await RunLeaderLoopAsync(elector.LeadershipToken);   // ends when leadership does

Set LeadershipOptions.LockKeyFormat for a naming convention, or LockKey for an exact override. With namespace billing, role scheduler, and format election:eu:{role}, the provider key is billing:lock:election:eu:scheduler. The default format is leader:{role}. An exact key takes precedence and is used literally, without placeholder expansion.

Formats require the case-sensitive {role} placeholder; every occurrence is replaced. All other characters are literal, including braces: {elections}:{role} resolves to {elections}:scheduler. Consumer braces do not select the Redis Cluster slot: cluster mode requires UseHashTags, which wraps the namespace first ({billing}:lock:{elections}:scheduler), and Redis hashes only the first {...}, so the slot stays on the namespace. Use an exact key for a name without the role. Resolved keys must be nonempty and have no whitespace or control characters. Both constructor and hosted composition check DistributedLock.MaxKeyLength (512 by default) before starting; a custom IDistributedLock remains responsible for its own length limit, which the leadership kernel cannot inspect.

LeaderElector.LockKey and LeadershipProbe.Describe(elector).LockKey report the captured consumer key before namespace prefixing. Mutating options does not re-key an existing elector, including on retries or resignation. Validate() checks syntax and timing; Validate(role, maxKeyLength) also checks expanded key length, and ResolveLockKey(role, maxKeyLength) resolves and validates the consumer key without starting an election.

Replicas must agree on the namespace and resolved key; independent roles sharing a namespace need distinct keys. Changing either creates a separate election: stop all old replicas and allow their leases to expire before starting the new identity, including on rollback.

The guarantee. At most one leader per role while clocks and the lock backend behave. On lease expiry there is a window, bounded by Leadership:Lease plus clock skew, in which the previous leader may still believe it leads; LeadershipToken bounds what it does with that belief only if the work honours the token. There is no fencing: Term counts this instance's acquisitions and is not a token a storage layer can check. Asynchronous replication in Redis and Valkey can lose an acquisition on failover, as it can for any lease. This is the same tier as the Kubernetes Lease election and is not consensus.

ILeadership is what consumers inject: Role, IsLeader, IsCoordinated, Term, LeadershipToken, WaitForLeadershipAsync, and OnChange. LeaderElector implements it and adds StartAsync, StopAsync, which releases the lease so a graceful restart hands over at once, and ResignAsync, which steps down and waits one retry interval before running again so another instance gets the first chance. A crashed process hands over when its lease expires.

The elector owns renewal instead of the lock's automatic extension, which stops at Locking:MaxHold; a leader renews for as long as it lives. Keep Leadership:Lease within Locking:MaxLease: a hosted elector fails at startup naming the role and both values, while a container-free one is capped by the lock. Keep Leadership:RenewInterval at most half the lease. An unreachable lock provider makes nobody leader, is logged once per outage, and is retried on the candidate cadence.

Over a lock that does not coordinate (Locking:Enabled = false) the lease is a placeholder every instance is granted, so the elector follows Leadership:WhenUncoordinated: Follow, the default, never leads, so replicas cannot all lead by accident; Lead leads without coordination, for a single instance or local development. The condition is logged once per role and reported by IsCoordinated and the probe. An exception the loop did not expect is logged as LeadershipLoopFaulted, backed off one retry interval, and survived; the loop never ends on its own, and every cadence is validated against the longest wait it can schedule.

LeaderChannel<T> is a bounded channel gated on a role: producers on every instance write to it, a leader's items reach the reader, and a follower's are accepted and discarded. That keeps a warm standby current without letting it act. Drops are counted on the meter by reason (follower, full, or loss) and summarised in the log at most once per LeaderChannel:DropReportInterval, with the tail written when the instance becomes leader.

var changes = new LeaderChannel<InventoryChange>("inventory-changes", leadership);
await changes.Writer.WriteAsync(change);          // discarded unless this instance leads
await foreach (var change in changes.Reader.ReadAllAsync(stoppingToken)) { ... }

With FullMode=Wait, losing leadership wakes producers waiting for capacity; follower readiness succeeds even while the old buffer is full. Asynchronous writes recheck the role after waiting. Already accepted buffered items remain readable: use the leadership token around leader-only side effects, because channel admission is not a fencing guarantee. LeaderChannelOptions.DrainOnLoss discards the buffer when leadership ends instead, counted and logged as loss; it narrows that window without closing it.

LeadershipProbe.Describe(elector) reports the composition without executing anything. Metrics and activities live under the HostLoom.Leadership meter and activity source. Install HostLoom.Leadership.DependencyInjection to register electors by role, and HostLoom.Scheduling.Leadership to run exclusive schedules on the leader only.

Product Compatible and additional computed target framework versions.
.NET 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on HostLoom.Leadership:

Package Downloads
HostLoom.Leadership.DependencyInjection

Microsoft.Extensions.DependencyInjection registration, keyed roles, options validation, and hosting for HostLoom leader election.

HostLoom.Leadership.Testing

A scripted ILeadership for testing leader-only consumers of HostLoom without an elector or a lock backend.

HostLoom.Scheduling.Leadership

Runs exclusive HostLoom schedules on the elected leader only, without a lock round trip per occurrence.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.17.0 0 10/25/2026
0.16.1 86 10/22/2026
0.16.0 191 10/14/2026
0.15.1 137 10/12/2026
0.15.0 137 10/4/2026
0.14.0 115 10/4/2026
0.13.0 125 9/28/2026
0.12.0 123 9/27/2026
0.11.0 125 9/25/2026
0.10.0 123 9/22/2026
0.9.0 119 9/22/2026