This commit is contained in:
master
2025-10-19 10:38:55 +03:00
parent 8dc7273e27
commit aef7ffb535
250 changed files with 17967 additions and 66 deletions

View File

@@ -0,0 +1,80 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using StellaOps.Scanner.WebService.Domain;
using StellaOps.Scanner.WebService.Utilities;
namespace StellaOps.Scanner.WebService.Services;
public sealed class InMemoryScanCoordinator : IScanCoordinator
{
private sealed record ScanEntry(ScanSnapshot Snapshot);
private readonly ConcurrentDictionary<string, ScanEntry> scans = new(StringComparer.OrdinalIgnoreCase);
private readonly TimeProvider timeProvider;
private readonly IScanProgressPublisher progressPublisher;
public InMemoryScanCoordinator(TimeProvider timeProvider, IScanProgressPublisher progressPublisher)
{
this.timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
this.progressPublisher = progressPublisher ?? throw new ArgumentNullException(nameof(progressPublisher));
}
public ValueTask<ScanSubmissionResult> SubmitAsync(ScanSubmission submission, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(submission);
var normalizedTarget = submission.Target.Normalize();
var metadata = submission.Metadata ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var scanId = ScanIdGenerator.Create(normalizedTarget, submission.Force, submission.ClientRequestId, metadata);
var now = timeProvider.GetUtcNow();
var eventData = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["force"] = submission.Force,
};
foreach (var pair in metadata)
{
eventData[$"meta.{pair.Key}"] = pair.Value;
}
ScanEntry entry = scans.AddOrUpdate(
scanId.Value,
_ => new ScanEntry(new ScanSnapshot(
scanId,
normalizedTarget,
ScanStatus.Pending,
now,
now,
null)),
(_, existing) =>
{
if (submission.Force)
{
var snapshot = existing.Snapshot with
{
Status = ScanStatus.Pending,
UpdatedAt = now,
FailureReason = null
};
return new ScanEntry(snapshot);
}
return existing;
});
var created = entry.Snapshot.CreatedAt == now;
var state = entry.Snapshot.Status.ToString();
progressPublisher.Publish(scanId, state, created ? "queued" : "requeued", eventData);
return ValueTask.FromResult(new ScanSubmissionResult(entry.Snapshot, created));
}
public ValueTask<ScanSnapshot?> GetAsync(ScanId scanId, CancellationToken cancellationToken)
{
if (scans.TryGetValue(scanId.Value, out var entry))
{
return ValueTask.FromResult<ScanSnapshot?>(entry.Snapshot);
}
return ValueTask.FromResult<ScanSnapshot?>(null);
}
}