PairWebRateProvider<TSeries> Class
Definition
- Namespace
- Bodu.Financial.ExchangeRates
- Assembly
- Bodu.Financial.ExchangeRates.dll
- Package
- Bodu.Financial.ExchangeRates 1.0.0
Provides the shared machinery for a WebRateProvider that fetches one currency pair per request from a remote feed - per-pair coverage tracking, single-flight request coalescing, the fetch-and-accumulate orchestration, and the diagnostic logging - leaving a derived type to supply only the feed identity and the feed-specific exception text. The actual fetch and parse are delegated to an IPairRateSource<TSeries>.
public abstract class PairWebRateProvider<TSeries> : WebRateProvider, IDatedRateProvider, IRateProvider, IPairRateLoader, IHistoricalRateProvider, IDisposable
Type Parameters
TSeriesThe source-specific series-metadata type surfaced through GetAvailablePairs().
- Inheritance
-
PairWebRateProvider<TSeries>
- Implements
- Derived
- Inherited Members
- Extension Methods
Remarks
This base sits between WebRateProvider (which owns the in-memory accumulator, the immutable snapshot, and the full lookup matrix) and a concrete pair-based source such as Yahoo Finance or OFX. It implements EnsureLoadedAsync(CurrencyPair, DateOnly, DateOnly, CancellationToken) and IsLoaded(CurrencyPair, DateOnly, DateOnly) with a gap-respecting per-pair DateRangeCoverage set so a request that straddles an unfetched interior gap is correctly treated as uncovered and re-fetched, and coalesces concurrent fetches of the same pair-and-window so only one request is in flight.
A derived type supplies ProviderId and may override CreateRangeInvertedException(DateOnly, DateOnly), FormatRateNotFound(string, string, DateOnly), and FormatPairForLog(CurrencyPair) to present feed-specific exception types, messages, and log labels.
using Bodu.Financial.ExchangeRates;
// A concrete pair-based source: the fetch/parse lives in an IPairRateSource<TSeries>;
// this type contributes only the feed identity. Coverage tracking, single-flight
// coalescing, and the full lookup surface come from the base classes.
public sealed class MyFeedRateProvider : PairWebRateProvider<MyFeedSeriesInfo>
{
public MyFeedRateProvider(MyFeedRateProviderOptions options, HttpClient httpClient)
: base(new MyFeedSource(httpClient, options), options, logger: null, ownedHttpClient: null, timeProvider: null)
{
}
protected override string ProviderId => "MyFeed";
}
Constructors
PairWebRateProvider(IPairRateSource<TSeries>, WebRateProviderOptions, ILogger?, HttpClient?, TimeProvider?)
Initializes a new instance of the PairWebRateProvider<TSeries> class.
protected PairWebRateProvider(IPairRateSource<TSeries> source, WebRateProviderOptions options, ILogger? logger, HttpClient? ownedHttpClient, TimeProvider? timeProvider)
Parameters
sourceIPairRateSource<TSeries>The source that fetches and parses a pair's observations.
optionsWebRateProviderOptionsThe provider options.
loggerILoggerThe logger that records pair downloads and on-demand network fetches. null selects Instance.
ownedHttpClientHttpClientThe HTTP client this provider should own and dispose, or null when the client is caller-supplied.
timeProviderTimeProviderThe time source used to resolve the current instant for the undated surfaces. null selects System.
Exceptions
- ArgumentNullException
Thrown when
sourceoroptionsis null.- ArgumentException
Thrown when
optionsfails validation.
Properties
AllowSynchronousNetworkAccess
Gets a value indicating whether a synchronous lookup may block to fetch a missing window on demand.
protected override sealed bool AllowSynchronousNetworkAccess { get; }
Property Value
Remarks
When enabled, the synchronous getters block on the async fetch, which can deadlock if invoked on a thread carrying a captured SynchronizationContext (classic ASP.NET, a WPF/WinForms UI thread). The synchronous path guards against this by throwing InvalidOperationException when Current is non-null; enable this only for code that calls the getters from a thread-pool thread (or use the asynchronous API).
DefaultLookback
Gets the look-back window used when a single-rate lookup must fetch on demand; the provider fetches the window ending on the requested date and spanning this duration.
protected override sealed TimeSpan DefaultLookback { get; }
Property Value
- TimeSpan
The look-back window.
HistoryAvailability
Gets the history depth this provider advertises: how far back it can serve rates.
public override RateHistoryAvailability HistoryAvailability { get; }
Property Value
- RateHistoryAvailability
The advertised availability; the base reports Unbounded. A derived type whose feed publishes only a bounded window overrides this to declare it.
Methods
EnsureLoadedAsync(CurrencyPair, DateOnly, DateOnly, CancellationToken)
Ensures the inclusive window for a pair has been fetched and accumulated, idempotently. Implementations perform their own coverage check, request coalescing, fetch, and accumulation (via AddObservations(IEnumerable<ExchangeRate>, DateTimeOffset?) and RebuildSnapshot() under SyncRoot).
protected override sealed ValueTask EnsureLoadedAsync(CurrencyPair pair, DateOnly startDate, DateOnly endDate, CancellationToken cancellationToken)
Parameters
pairCurrencyPairThe currency pair to ensure data for. Feeds that fetch by range, feed, or file may ignore it.
startDateDateOnlyThe inclusive start of the window.
endDateDateOnlyThe inclusive end of the window.
cancellationTokenCancellationTokenA token to observe while awaiting the fetch.
Returns
- ValueTask
A task that completes when the window has been loaded.
FormatPairForLog(CurrencyPair)
Formats the label used for a pair in the download log messages. The default returns the FROM/TO ISO-code
pair; a derived type may override it to log a feed-specific identifier such as a ticker.
protected virtual string FormatPairForLog(CurrencyPair pair)
Parameters
pairCurrencyPairThe pair being logged.
Returns
- string
The label to log.
GetAvailablePairs()
Gets the currency pairs fetched so far.
public IReadOnlyCollection<TSeries> GetAvailablePairs()
Returns
- IReadOnlyCollection<TSeries>
A snapshot of the discovered series, one per currency pair.
IsLoaded(CurrencyPair, DateOnly, DateOnly)
Reports whether the inclusive window for a pair has already been fetched, so the synchronous lookup path can skip a redundant blocking fetch.
protected override sealed bool IsLoaded(CurrencyPair pair, DateOnly startDate, DateOnly endDate)
Parameters
pairCurrencyPairThe currency pair to test.
startDateDateOnlyThe inclusive start of the window.
endDateDateOnlyThe inclusive end of the window.
Returns
OnObservationIngested(ExchangeRate)
Called once per observation as it is ingested, for derived-type diagnostics. The default does nothing.
protected override sealed void OnObservationIngested(ExchangeRate rate)
Parameters
rateExchangeRateThe observation being ingested.
OnSynchronousNetworkFetch(DateOnly)
Called after a synchronous lookup blocks to fetch on demand, for derived-type diagnostics. The default does nothing.
protected override sealed void OnSynchronousNetworkFetch(DateOnly date)
Parameters
dateDateOnlyThe date around which the fetch was performed.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |