Table of Contents

RateCacheRules Class

Definition

Namespace
Bodu.Financial.ExchangeRates.Caching
Assembly
Bodu.Financial.ExchangeRates.Caching.dll
Package
Bodu.Financial.ExchangeRates.Caching 1.0.0
Source
RateCacheRules.cs

Provides the storage-agnostic freshness, validity, merge, and coverage rules shared by every IRateCache implementation, so the in-memory, file, SQLite, and distributed backends apply one authoritative policy and differ only in how they read and write their bytes.

public static class RateCacheRules
Inheritance
RateCacheRules
Inherited Members

Remarks

Every method operates on the public CachedRate row type and on a plain (Start, End, FetchedAtUtc) coverage tuple, so a backend can call these rules without exposing its internal state representation. The rules are pure: they read their inputs, evaluate freshness and validity against the supplied instant, and return new collections, leaving all persistence and locking to the caller.

Freshness is a strict less-than comparison - a row or window exactly one duration old is stale - and validity allows a one-minute clock-skew tolerance so a row stamped marginally ahead of the evaluating clock is not discarded. These are the same thresholds the cache surface has always applied; centralising them here keeps every backend identical, which the shared cache contract tests assert.

Methods

BuildCoverage(IEnumerable<(DateOnly Start, DateOnly End, DateTimeOffset FetchedAtUtc)>, TimeSpan, DateTimeOffset)

Folds the still-fresh coverage windows for a pair into a DateRangeCoverage, evaluated against asOf.

public static DateRangeCoverage BuildCoverage(IEnumerable<(DateOnly Start, DateOnly End, DateTimeOffset FetchedAtUtc)> windows, TimeSpan duration, DateTimeOffset asOf)

Parameters

windows IEnumerable<(DateOnly Start, DateOnly End, DateTimeOffset FetchedAtUtc)>

The recorded coverage windows to fold.

duration TimeSpan

The duration a recorded coverage window remains fresh after it was fetched.

asOf DateTimeOffset

The instant against which coverage freshness is evaluated.

Returns

DateRangeCoverage

A DateRangeCoverage describing the days known to have been fetched and still fresh; empty when no fresh window remains.

Exceptions

ArgumentNullException

Thrown when windows is null.

IsValid(CachedRate, DateTimeOffset)

Reports whether a cached row is semantically valid against the evaluation instant.

public static bool IsValid(CachedRate row, DateTimeOffset asOf)

Parameters

row CachedRate

The cached row to validate.

asOf DateTimeOffset

The instant against which the caching instant is checked for implausible future stamps.

Returns

bool

false when the row carries a non-positive rate, a default (unset) date, or a caching instant implausibly far in the future of asOf; otherwise true.

Remarks

Invalid rows are silently skipped on both write (rejecting bad incoming data) and read (rejecting persisted or tampered rows) so a malformed cache never surfaces a nonsensical rate. A small clock-skew tolerance is allowed so a row stamped marginally ahead of the evaluating clock is not discarded.

MergeCoverage(IEnumerable<(DateOnly Start, DateOnly End, DateTimeOffset FetchedAtUtc)>, DateOnly, DateOnly, TimeSpan, DateTimeOffset)

Appends the newly fetched window start..end stamped at asOf to the still-fresh existing windows, dropping windows that are no longer fresh.

public static List<(DateOnly Start, DateOnly End, DateTimeOffset FetchedAtUtc)> MergeCoverage(IEnumerable<(DateOnly Start, DateOnly End, DateTimeOffset FetchedAtUtc)> existing, DateOnly start, DateOnly end, TimeSpan duration, DateTimeOffset asOf)

Parameters

existing IEnumerable<(DateOnly Start, DateOnly End, DateTimeOffset FetchedAtUtc)>

The windows already recorded for the pair.

start DateOnly

The inclusive first date of the newly fetched range.

end DateOnly

The inclusive last date of the newly fetched range.

duration TimeSpan

The duration a recorded coverage window remains fresh after it was fetched.

asOf DateTimeOffset

The instant the new window is stamped with and against which stale windows are pruned.

Returns

List<(DateOnly Start, DateOnly End, DateTimeOffset FetchedAtUtc)>

The pruned existing windows with the new window appended.

Exceptions

ArgumentNullException

Thrown when existing is null.

ArgumentOutOfRangeException

Thrown when start is later than end.

MergeRows(IEnumerable<CachedRate>, IEnumerable<CachedRate>, TimeSpan, DateTimeOffset)

Merges incoming rows into existing rows so the most recently cached row wins per date, dropping rows that are stale or semantically invalid, and ordering the result by date.

public static List<CachedRate> MergeRows(IEnumerable<CachedRate> existing, IEnumerable<CachedRate> incoming, TimeSpan duration, DateTimeOffset asOf)

Parameters

existing IEnumerable<CachedRate>

The rows already stored for the pair.

incoming IEnumerable<CachedRate>

The rows being stored, which take precedence on a tie by caching instant.

duration TimeSpan

The duration a cached row remains fresh after it was cached.

asOf DateTimeOffset

The instant against which staleness and validity are evaluated.

Returns

List<CachedRate>

The merged, pruned rows ordered ascending by date; empty when none survive.

Remarks

An incoming invalid row is skipped before it can overwrite a valid stored row for the same date. After the merge, every surviving row is re-checked for freshness and validity so the store self-cleans on each write.

Exceptions

ArgumentNullException

Thrown when existing or incoming is null.

SelectFresh(IEnumerable<CachedRate>, TimeSpan, DateTimeOffset)

Selects the rows that are both semantically valid and still fresh at asOf, ordered by date.

public static List<CachedRate> SelectFresh(IEnumerable<CachedRate> rows, TimeSpan duration, DateTimeOffset asOf)

Parameters

rows IEnumerable<CachedRate>

The candidate rows to filter.

duration TimeSpan

The duration a cached row remains fresh after it was cached.

asOf DateTimeOffset

The instant against which freshness and validity are evaluated.

Returns

List<CachedRate>

The fresh, valid rows ordered ascending by date; empty when none qualify.

Exceptions

ArgumentNullException

Thrown when rows is null.

Applies to

ProductVersions
.NET8, 10