sprints work

This commit is contained in:
master
2026-01-11 11:19:40 +02:00
parent f6ef1ef337
commit 582a41d7a9
72 changed files with 2680 additions and 390 deletions

View File

@@ -20,6 +20,7 @@ public sealed class CiscoProviderMetadataLoader
private readonly ILogger<CiscoProviderMetadataLoader> _logger;
private readonly CiscoConnectorOptions _options;
private readonly IFileSystem _fileSystem;
private readonly TimeProvider _timeProvider;
private readonly JsonSerializerOptions _serializerOptions;
private readonly SemaphoreSlim _semaphore = new(1, 1);
@@ -28,7 +29,8 @@ public sealed class CiscoProviderMetadataLoader
IMemoryCache memoryCache,
IOptions<CiscoConnectorOptions> options,
ILogger<CiscoProviderMetadataLoader> logger,
IFileSystem? fileSystem = null)
IFileSystem? fileSystem = null,
TimeProvider? timeProvider = null)
{
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
_memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
@@ -36,6 +38,7 @@ public sealed class CiscoProviderMetadataLoader
ArgumentNullException.ThrowIfNull(options);
_options = options.Value ?? throw new ArgumentNullException(nameof(options));
_fileSystem = fileSystem ?? new FileSystem();
_timeProvider = timeProvider ?? TimeProvider.System;
_serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
PropertyNameCaseInsensitive = true,
@@ -45,7 +48,8 @@ public sealed class CiscoProviderMetadataLoader
public async Task<CiscoProviderMetadataResult> LoadAsync(CancellationToken cancellationToken)
{
if (_memoryCache.TryGetValue<CacheEntry>(CacheKey, out var cached) && cached is not null && !cached.IsExpired())
var now = _timeProvider.GetUtcNow();
if (_memoryCache.TryGetValue<CacheEntry>(CacheKey, out var cached) && cached is not null && !cached.IsExpired(now))
{
_logger.LogDebug("Returning cached Cisco provider metadata (expires {Expires}).", cached.ExpiresAt);
return new CiscoProviderMetadataResult(cached.Provider, cached.FetchedAt, cached.FromOffline, true);
@@ -54,7 +58,8 @@ public sealed class CiscoProviderMetadataLoader
await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
if (_memoryCache.TryGetValue<CacheEntry>(CacheKey, out cached) && cached is not null && !cached.IsExpired())
now = _timeProvider.GetUtcNow();
if (_memoryCache.TryGetValue<CacheEntry>(CacheKey, out cached) && cached is not null && !cached.IsExpired(now))
{
return new CiscoProviderMetadataResult(cached.Provider, cached.FetchedAt, cached.FromOffline, true);
}
@@ -76,8 +81,8 @@ public sealed class CiscoProviderMetadataLoader
{
var entry = offline with
{
FetchedAt = DateTimeOffset.UtcNow,
ExpiresAt = DateTimeOffset.UtcNow + _options.MetadataCacheDuration,
FetchedAt = _timeProvider.GetUtcNow(),
ExpiresAt = _timeProvider.GetUtcNow() + _options.MetadataCacheDuration,
FromOffline = true,
};
StoreCache(entry);
@@ -115,8 +120,8 @@ public sealed class CiscoProviderMetadataLoader
_logger.LogDebug("Cisco provider metadata not modified (etag {ETag}).", previous.ETag);
return previous with
{
FetchedAt = DateTimeOffset.UtcNow,
ExpiresAt = DateTimeOffset.UtcNow + _options.MetadataCacheDuration,
FetchedAt = _timeProvider.GetUtcNow(),
ExpiresAt = _timeProvider.GetUtcNow() + _options.MetadataCacheDuration,
};
}
@@ -140,8 +145,8 @@ public sealed class CiscoProviderMetadataLoader
return new CacheEntry(
provider,
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow + _options.MetadataCacheDuration,
_timeProvider.GetUtcNow(),
_timeProvider.GetUtcNow() + _options.MetadataCacheDuration,
etagHeader,
FromOffline: false);
}
@@ -169,7 +174,7 @@ public sealed class CiscoProviderMetadataLoader
{
var payload = _fileSystem.File.ReadAllText(_options.OfflineSnapshotPath);
var provider = ParseProvider(payload);
return new CacheEntry(provider, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow + _options.MetadataCacheDuration, null, true);
return new CacheEntry(provider, _timeProvider.GetUtcNow(), _timeProvider.GetUtcNow() + _options.MetadataCacheDuration, null, true);
}
catch (Exception ex)
{
@@ -242,7 +247,7 @@ public sealed class CiscoProviderMetadataLoader
string? ETag,
bool FromOffline)
{
public bool IsExpired() => DateTimeOffset.UtcNow >= ExpiresAt;
public bool IsExpired(DateTimeOffset now) => now >= ExpiresAt;
}
}

View File

@@ -25,6 +25,7 @@ public sealed class RancherHubMetadataLoader
private readonly RancherHubTokenProvider _tokenProvider;
private readonly IFileSystem _fileSystem;
private readonly ILogger<RancherHubMetadataLoader> _logger;
private readonly TimeProvider _timeProvider;
private readonly SemaphoreSlim _semaphore = new(1, 1);
private readonly JsonDocumentOptions _documentOptions;
@@ -33,13 +34,15 @@ public sealed class RancherHubMetadataLoader
IMemoryCache memoryCache,
RancherHubTokenProvider tokenProvider,
IFileSystem fileSystem,
ILogger<RancherHubMetadataLoader> logger)
ILogger<RancherHubMetadataLoader> logger,
TimeProvider? timeProvider = null)
{
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
_memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
_tokenProvider = tokenProvider ?? throw new ArgumentNullException(nameof(tokenProvider));
_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_timeProvider = timeProvider ?? TimeProvider.System;
_documentOptions = new JsonDocumentOptions
{
CommentHandling = JsonCommentHandling.Skip,
@@ -52,7 +55,7 @@ public sealed class RancherHubMetadataLoader
ArgumentNullException.ThrowIfNull(options);
var cacheKey = CreateCacheKey(options);
if (_memoryCache.TryGetValue<CacheEntry>(cacheKey, out var cached) && cached is not null && !cached.IsExpired())
if (_memoryCache.TryGetValue<CacheEntry>(cacheKey, out var cached) && cached is not null && !cached.IsExpired(_timeProvider.GetUtcNow()))
{
_logger.LogDebug("Returning cached Rancher hub metadata (expires {Expires}).", cached.ExpiresAt);
return new RancherHubMetadataResult(cached.Metadata, cached.FetchedAt, FromCache: true, cached.FromOfflineSnapshot);
@@ -61,7 +64,7 @@ public sealed class RancherHubMetadataLoader
await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
if (_memoryCache.TryGetValue<CacheEntry>(cacheKey, out cached) && cached is not null && !cached.IsExpired())
if (_memoryCache.TryGetValue<CacheEntry>(cacheKey, out cached) && cached is not null && !cached.IsExpired(_timeProvider.GetUtcNow()))
{
return new RancherHubMetadataResult(cached.Metadata, cached.FetchedAt, FromCache: true, cached.FromOfflineSnapshot);
}
@@ -131,8 +134,8 @@ public sealed class RancherHubMetadataLoader
_logger.LogDebug("Rancher hub discovery document not modified (etag {ETag}).", previous.ETag);
return previous with
{
FetchedAt = DateTimeOffset.UtcNow,
ExpiresAt = DateTimeOffset.UtcNow + options.MetadataCacheDuration,
FetchedAt = _timeProvider.GetUtcNow(),
ExpiresAt = _timeProvider.GetUtcNow() + options.MetadataCacheDuration,
FromOfflineSnapshot = false,
};
}
@@ -142,8 +145,8 @@ public sealed class RancherHubMetadataLoader
var metadata = ParseMetadata(payload, options);
var entry = new CacheEntry(
metadata,
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow + options.MetadataCacheDuration,
_timeProvider.GetUtcNow(),
_timeProvider.GetUtcNow() + options.MetadataCacheDuration,
response.Headers.ETag?.ToString(),
FromOfflineSnapshot: false,
Payload: payload);
@@ -177,8 +180,8 @@ public sealed class RancherHubMetadataLoader
var metadata = ParseMetadata(payload, options);
return new CacheEntry(
metadata,
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow + options.MetadataCacheDuration,
_timeProvider.GetUtcNow(),
_timeProvider.GetUtcNow() + options.MetadataCacheDuration,
ETag: null,
FromOfflineSnapshot: true,
Payload: payload);
@@ -422,7 +425,7 @@ public sealed class RancherHubMetadataLoader
bool FromOfflineSnapshot,
string? Payload)
{
public bool IsExpired() => DateTimeOffset.UtcNow >= ExpiresAt;
public bool IsExpired(DateTimeOffset now) => now >= ExpiresAt;
}
}