Repository navigation
HostLoom 0.16.0
The seventeenth release of HostLoom. Its headline is a new package family — lease-based node-ID leasing over the distributed lock, for the services that must tell their instances apart by a small integer, a Snowflake-style worker ID or a shard slot, without ever letting two holders share one. Alongside it, a mapping registration a host may reach twice without failing, a bound on the queue a Redis invalidation subscription fans into, and a core package that no longer draws the ASP.NET Core shared framework.
HostLoom.NodeLeasing leases a pool of small integer IDs to the instances of a service. One elector per pool hands out the IDs zero to NodeLeasing:PoolSize minus one, scanning with the ID it last held first, for stickiness across a restart, then ascending from a random offset, and taking the first ID a skip-if-busy acquisition grants on nodeid:{pool}:{id}. The holder renews explicitly — a renewal the backend refuses or a lease that runs out steps it back to candidate at once — and an assignment token bounds what it does with a belief that outlives the lease. The guarantee is stated as narrowly as it is kept: at most one holder per ID while clocks and the lock backend behave, with a window on expiry bounded by NodeLeasing:Lease plus clock skew, and no fencing. HostLoom.NodeLeasing.DependencyInjection registers pools keyed by name with options validation and hosting, and HostLoom.NodeLeasing.Testing ships the scripted INodeLeasing double for consumers that only need to know which ID they were handed.
MappingBuilder.TryAdd<TMapper>, its explicit-pair overload, and the TryAddUpdate counterparts close the composition gap in mapping registration: when a host composes several builders and one shared registration is reached more than once, a pair already registered by the same map class — with its lifetime — is left in place, while a different implementation for that pair is still rejected as a duplicate. The factory and instance overloads keep no TryAdd counterpart, because a registration built from a runtime object cannot be recognized as the same map on a second call.
HostLoom.Redis bounds the queue every invalidation subscription fans into. That queue was previously unbounded: a server publishing faster than the local reader could apply messages — a chatty keyspace, a stalled event loop — grew memory without limit and without a signal. The queue now holds Caching:Invalidation:MaxPending messages and drops the newest undelivered one past that bound, reporting each drop on the new DroppedMessages property and the hostloom.redis.invalidation.dropped counter. The in-process entries a dropped message would have removed stay until they expire, the same trade the cache's own pending queue already makes.
HostLoom no longer references the Microsoft.AspNetCore.App shared framework. The kernel never called an ASP.NET Core API — it consumes only hosting, dependency-injection, logging, options, and health-check abstractions — and it now references exactly those five Microsoft.Extensions.* packages, so a worker or console consumer no longer resolves the ASP.NET Core runtime. Applications that host on ASP.NET Core already reference the framework themselves and are unaffected. The core package still makes no Native AOT claim.
Upgrading from 0.15.1 changes no signature an application compiles against. The one dependency-level change is HostLoom's framework reference, and an application that hosts on ASP.NET Core references the framework itself, so it is unaffected; a worker or console consumer simply stops resolving a runtime it never used. HostLoom.NodeLeasing, HostLoom.NodeLeasing.DependencyInjection, and HostLoom.NodeLeasing.Testing are published for the first time; the remaining packages carry the changes above and nothing else. @hostloom/websocket-client is not part of this NuGet set and has no changes since its 0.3.0 release.
Added
HostLoom.NodeLeasing, lease-based node-ID leasing over the distributed lock: a pool of small integer IDs (Snowflake-style worker IDs), one elector per pool with a sticky scan and explicit renewal, an assignment token, and the honest guarantee statement (at most one holder per ID bounded by the lease plus clock skew, no fencing);HostLoom.NodeLeasing.DependencyInjection, pools keyed by name with options validation and hosting; andHostLoom.NodeLeasing.Testing, the scriptedINodeLeasingdouble.HostLoom.Redisreports invalidation messages its subscription fan-in drops under load: aDroppedMessagesproperty onRedisCacheInvalidationChanneland ahostloom.redis.invalidation.droppedcounter tagged by namespace.MappingBuilder.TryAdd<TMapper>andTryAdd<TSource, TDestination, TMapper>, withTryAddUpdatecounterparts, for a registration a host may reach twice: a pair already registered by the same map class is left in place — with its lifetime — while a different implementation for the same pair is still rejected as a duplicate. The factory and instance overloads keep noTryAddcounterpart, because a registration built from a runtime object cannot be recognized as the same map on a second call.
Changed
- The
HostLoom.Redisinvalidation fan-in queue is bounded byCaching:Invalidation:MaxPendinginstead of growing without limit. A Redis instance publishing faster than the local reader can apply now drops the newest undelivered message and reports each drop, and the entries it would have removed stay in the in-process tier until they expire — the same trade the cache's own pending queue already makes. HostLoomreferences the fiveMicrosoft.Extensions.*packages it actually uses instead of theMicrosoft.AspNetCore.Appshared framework, so worker and console consumers no longer pull in the ASP.NET Core runtime. Applications that host on ASP.NET Core are unaffected.