using Hangfire; namespace Kbx.Shared.ExternalData; public sealed class KbxExternalDataRefreshScheduler(IBackgroundJobClient jobs):IKbxExternalDataRefreshScheduler { public Task ScheduleEntryAsync(Guid tenantId,string datasetId,string cacheKey,CancellationToken cancellationToken) { jobs.Enqueue(x=>x.RunEntryAsync(tenantId,datasetId,cacheKey,CancellationToken.None)); return Task.CompletedTask; } public Task ScheduleDatasetAsync(Guid tenantId,string datasetId,CancellationToken cancellationToken) { jobs.Enqueue(x=>x.RunDatasetAsync(tenantId,datasetId,CancellationToken.None)); return Task.CompletedTask; } } public sealed class KbxExternalDataRefreshJob(KbxExternalDataRefresherRegistry registry) { public Task RunEntryAsync(Guid tenantId,string datasetId,string cacheKey,CancellationToken ct)=>registry.GetRequired(datasetId).RefreshEntryAsync(tenantId,cacheKey,ct); public Task RunDatasetAsync(Guid tenantId,string datasetId,CancellationToken ct)=>registry.GetRequired(datasetId).RefreshKnownEntriesAsync(tenantId,ct); } public interface IKbxExternalDataDatasetRefresher { string DatasetId { get; } Task RefreshEntryAsync(Guid tenantId,string cacheKey,CancellationToken ct); Task RefreshKnownEntriesAsync(Guid tenantId,CancellationToken ct); } public sealed class KbxExternalDataRefresherRegistry(IEnumerable refreshers) { private readonly IReadOnlyDictionary map=refreshers.ToDictionary(x=>x.DatasetId,StringComparer.Ordinal); public IKbxExternalDataDatasetRefresher GetRequired(string datasetId)=>map.TryGetValue(datasetId,out var r)?r:throw new InvalidOperationException($"No external-data refresher registered for {datasetId}."); }