Table of Contents

NotableDateCachingOptions Class

Definition

Namespace
Bodu.Globalization.Calendar.Caching
Assembly
Bodu.Globalization.Calendar.Caching.dll
Package
Bodu.Globalization.Calendar.Caching 1.0.0
Source
NotableDateCachingOptions.cs

Configures a CachingNotableDateService: how long a computed year stays fresh, the resource-version token used when no resource provider is observed, the on-disk cache location, and the log levels of the per-lookup hit and miss diagnostics.

public sealed class NotableDateCachingOptions
Inheritance
NotableDateCachingOptions
Inherited Members
Extension Methods

Remarks

Every member carries a working default, so the options bind cleanly through Microsoft.Extensions.Options and require no configuration for the common case.

Freshness has two independent triggers. Ttl expires a cached year a fixed duration after it was computed, a safety net against drift. A change in the resource currently in effect changes the version token and invalidates every entry computed under the previous version, so a reload always forces a recompute regardless of the time-to-live.

Constructors

NotableDateCachingOptions()

public NotableDateCachingOptions()

Properties

CacheDirectory

Gets or sets the directory used by the default on-disk cache.

public string? CacheDirectory { get; set; }

Property Value

string

The cache directory, or null to use a bodu-notable-dates folder under the system temporary path.

CacheHitLogLevel

Gets or sets the level at which a year served from the cache is logged.

public LogLevel CacheHitLogLevel { get; set; }

Property Value

LogLevel

The log level; defaults to Information.

CacheMissLogLevel

Gets or sets the level at which a year recomputed on a cache miss and cached is logged.

public LogLevel CacheMissLogLevel { get; set; }

Property Value

LogLevel

The log level; defaults to Information.

RefreshAheadFraction

Gets or sets the fraction of the effective time-to-live after which a cache hit, while still served immediately, additionally schedules a single background recompute of the served year, so a hot territory is recomputed before it expires and no caller ever absorbs the recompute latency.

public double RefreshAheadFraction { get; set; }

Property Value

double

A fraction in [0, 1); defaults to 0, which disables refresh-ahead entirely and preserves the plain serve-until-expiry behaviour.

Remarks

Refresh-ahead is access-triggered: no timers run, and only a year actually served from the cache can schedule a recompute. When a hit's served entry is older than this fraction of the effective (post-jitter) time-to-live, at most one background recompute per territory, year, and resource version is started; concurrent aged hits for the same key join the pending recompute rather than duplicating it. Because the fraction is below 1, the recompute always begins before the entry expires, so a continuously hot territory never surfaces a miss.

The background recompute shares the single-flight guard with genuine misses, so a miss that arrives while a refresh is computing is served the refreshed value; such a joining caller is counted as neither a hit nor a miss. A recompute that fails is swallowed after logging - the hit it piggybacked on was already served - and the next aged hit schedules a fresh attempt. Disposing the service prevents new recomputes from being scheduled and abandons pending ones without draining them.

ResourceVersion

Gets or sets the resource-version token used to key cache entries when the caching service observes no INotableDateResourceProvider.

public string? ResourceVersion { get; set; }

Property Value

string

The fixed version token, or null to use a built-in default. Ignored when a resource provider is observed, in which case the token is derived from the resource in effect.

Remarks

Set this to the data version of the resource the wrapped service resolves against when that service is not reloadable, so bumping it invalidates the cache after a data update. When a reloadable resource provider is observed, the token is derived from the resource identity and reload generation instead and this value is unused.

Ttl

Gets or sets the duration a computed year stays fresh after it was computed.

public TimeSpan Ttl { get; set; }

Property Value

TimeSpan

The time-to-live; defaults to 30 days.

Remarks

Validation requires only a strictly positive duration; there is no upper bound. Because notable-date resolution is deterministic for a given resource version, the version trigger handles data changes and this time-to-live is a coarse safety net; an extreme duration effectively disables the time-based trigger.

TtlJitter

Gets or sets the maximum fraction of Ttl that is deterministically shaved off per territory, so territories warmed together do not all expire - and recompute - at the same instant.

public double TtlJitter { get; set; }

Property Value

double

A fraction in [0, 1); defaults to 0, which disables jitter and preserves the exact configured time-to-live.

Remarks

The reduction is derived from a stable hash of the normalized territory (not from randomness), so a given territory's effective time-to-live is identical across instances and processes and deterministic under test. The jitter is keyed by territory rather than by territory and year so the batch and per-year read paths - which share one time-to-live per resolution - always agree on freshness. Jitter only ever shortens the duration, so no year is served longer than the configured time-to-live allows; the trade-off is that a territory may recompute up to this fraction of its time-to-live early.

Methods

TryValidate(out string?)

Attempts to validate the options without throwing, reporting the first invariant that is violated.

public bool TryValidate(out string? error)

Parameters

error string

When this method returns false, a message describing the first violated invariant; otherwise null.

Returns

bool

true when every invariant holds; otherwise false.

Validate()

Validates the option values, throwing when a rule is violated.

public void Validate()

Remarks

This throwing form preserves the ParamName of the offending option. The dependency-injection registration instead wires TryValidate(out string?) into ValidateOnStart.

Exceptions

ArgumentException

Thrown when Ttl is not strictly positive, or when CacheHitLogLevel or CacheMissLogLevel is not a defined LogLevel.

Applies to

ProductVersions
.NET8, 10