save checkpoint
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.DependencyInjection\StellaOps.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Cryptography\StellaOps.Cryptography.csproj" />
|
||||
<ProjectReference Include="..\..\Telemetry\StellaOps.Telemetry.Core\StellaOps.Telemetry.Core\StellaOps.Telemetry.Core.csproj" />
|
||||
<ProjectReference Include="..\__Libraries\StellaOps.Replay.Core\StellaOps.Replay.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -304,92 +304,5 @@ public sealed class FeedSnapshotServiceTests
|
||||
}
|
||||
}
|
||||
|
||||
#region Test helpers
|
||||
|
||||
internal sealed class InMemoryFeedSnapshotBlobStore : IFeedSnapshotBlobStore
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, FeedSnapshotBlob> _blobs = new();
|
||||
|
||||
public Task StoreAsync(FeedSnapshotBlob blob, CancellationToken ct = default)
|
||||
{
|
||||
_blobs[blob.Digest] = blob;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<FeedSnapshotBlob?> GetByDigestAsync(string digest, CancellationToken ct = default)
|
||||
{
|
||||
_blobs.TryGetValue(digest, out var blob);
|
||||
return Task.FromResult(blob);
|
||||
}
|
||||
|
||||
public Task<bool> ExistsAsync(string digest, CancellationToken ct = default)
|
||||
{
|
||||
return Task.FromResult(_blobs.ContainsKey(digest));
|
||||
}
|
||||
|
||||
public Task DeleteAsync(string digest, CancellationToken ct = default)
|
||||
{
|
||||
_blobs.TryRemove(digest, out _);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class InMemoryFeedSnapshotIndexStore : IFeedSnapshotIndexStore
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, List<FeedSnapshotIndexEntry>> _index = new();
|
||||
|
||||
public Task IndexSnapshotAsync(FeedSnapshotIndexEntry entry, CancellationToken ct = default)
|
||||
{
|
||||
var entries = _index.GetOrAdd(entry.ProviderId, _ => new List<FeedSnapshotIndexEntry>());
|
||||
lock (entries)
|
||||
{
|
||||
entries.Add(entry);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<FeedSnapshotIndexEntry?> FindSnapshotAtTimeAsync(
|
||||
string providerId,
|
||||
DateTimeOffset pointInTime,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
if (!_index.TryGetValue(providerId, out var entries))
|
||||
{
|
||||
return Task.FromResult<FeedSnapshotIndexEntry?>(null);
|
||||
}
|
||||
|
||||
lock (entries)
|
||||
{
|
||||
var entry = entries
|
||||
.Where(e => e.CapturedAt <= pointInTime)
|
||||
.OrderByDescending(e => e.CapturedAt)
|
||||
.FirstOrDefault();
|
||||
return Task.FromResult(entry);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ImmutableArray<FeedSnapshotIndexEntry>> ListSnapshotsAsync(
|
||||
string providerId,
|
||||
DateTimeOffset from,
|
||||
DateTimeOffset to,
|
||||
int limit,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
if (!_index.TryGetValue(providerId, out var entries))
|
||||
{
|
||||
return Task.FromResult(ImmutableArray<FeedSnapshotIndexEntry>.Empty);
|
||||
}
|
||||
|
||||
lock (entries)
|
||||
{
|
||||
var result = entries
|
||||
.Where(e => e.CapturedAt >= from && e.CapturedAt <= to)
|
||||
.OrderBy(e => e.CapturedAt)
|
||||
.Take(limit)
|
||||
.ToImmutableArray();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
// Test helpers (InMemoryFeedSnapshotBlobStore, InMemoryFeedSnapshotIndexStore)
|
||||
// are defined in PointInTimeAdvisoryResolverTests.cs in the same namespace.
|
||||
|
||||
@@ -334,112 +334,5 @@ public sealed class PointInTimeQueryEndpointsTests
|
||||
}
|
||||
}
|
||||
|
||||
#region Test helpers (duplicated for standalone test execution)
|
||||
|
||||
internal sealed class InMemoryFeedSnapshotBlobStore : IFeedSnapshotBlobStore
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, FeedSnapshotBlob> _blobs = new();
|
||||
|
||||
public Task StoreAsync(FeedSnapshotBlob blob, CancellationToken ct = default)
|
||||
{
|
||||
_blobs[blob.Digest] = blob;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<FeedSnapshotBlob?> GetByDigestAsync(string digest, CancellationToken ct = default)
|
||||
{
|
||||
_blobs.TryGetValue(digest, out var blob);
|
||||
return Task.FromResult(blob);
|
||||
}
|
||||
|
||||
public Task<bool> ExistsAsync(string digest, CancellationToken ct = default)
|
||||
{
|
||||
return Task.FromResult(_blobs.ContainsKey(digest));
|
||||
}
|
||||
|
||||
public Task DeleteAsync(string digest, CancellationToken ct = default)
|
||||
{
|
||||
_blobs.TryRemove(digest, out _);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class InMemoryFeedSnapshotIndexStore : IFeedSnapshotIndexStore
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, List<FeedSnapshotIndexEntry>> _index = new();
|
||||
|
||||
public Task IndexSnapshotAsync(FeedSnapshotIndexEntry entry, CancellationToken ct = default)
|
||||
{
|
||||
var entries = _index.GetOrAdd(entry.ProviderId, _ => new List<FeedSnapshotIndexEntry>());
|
||||
lock (entries)
|
||||
{
|
||||
entries.Add(entry);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<FeedSnapshotIndexEntry?> FindSnapshotAtTimeAsync(
|
||||
string providerId,
|
||||
DateTimeOffset pointInTime,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
if (!_index.TryGetValue(providerId, out var entries))
|
||||
{
|
||||
return Task.FromResult<FeedSnapshotIndexEntry?>(null);
|
||||
}
|
||||
|
||||
lock (entries)
|
||||
{
|
||||
var entry = entries
|
||||
.Where(e => e.CapturedAt <= pointInTime)
|
||||
.OrderByDescending(e => e.CapturedAt)
|
||||
.FirstOrDefault();
|
||||
return Task.FromResult(entry);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ImmutableArray<FeedSnapshotIndexEntry>> ListSnapshotsAsync(
|
||||
string providerId,
|
||||
DateTimeOffset from,
|
||||
DateTimeOffset to,
|
||||
int limit,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
if (!_index.TryGetValue(providerId, out var entries))
|
||||
{
|
||||
return Task.FromResult(ImmutableArray<FeedSnapshotIndexEntry>.Empty);
|
||||
}
|
||||
|
||||
lock (entries)
|
||||
{
|
||||
var result = entries
|
||||
.Where(e => e.CapturedAt >= from && e.CapturedAt <= to)
|
||||
.OrderBy(e => e.CapturedAt)
|
||||
.Take(limit)
|
||||
.ToImmutableArray();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class TestAdvisoryExtractor : IAdvisoryExtractor
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, AdvisoryData> _advisories = new();
|
||||
|
||||
public void SetAdvisory(string cveId, AdvisoryData advisory)
|
||||
{
|
||||
_advisories[cveId] = advisory;
|
||||
}
|
||||
|
||||
public Task<AdvisoryData?> ExtractAdvisoryAsync(
|
||||
string cveId,
|
||||
byte[] content,
|
||||
FeedSnapshotFormat format,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
_advisories.TryGetValue(cveId, out var advisory);
|
||||
return Task.FromResult(advisory);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
// Test helpers (InMemoryFeedSnapshotBlobStore, InMemoryFeedSnapshotIndexStore, TestAdvisoryExtractor)
|
||||
// are defined in PointInTimeAdvisoryResolverTests.cs in the same namespace.
|
||||
|
||||
Reference in New Issue
Block a user