notify doctors work, audit work, new product advisory sprints
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
@@ -5,8 +6,8 @@ namespace StellaOps.Evidence.Budgets;
|
||||
|
||||
public interface IEvidenceBudgetService
|
||||
{
|
||||
BudgetCheckResult CheckBudget(Guid scanId, EvidenceItem item);
|
||||
BudgetStatus GetBudgetStatus(Guid scanId);
|
||||
Task<BudgetCheckResult> CheckBudgetAsync(Guid scanId, EvidenceItem item, CancellationToken ct);
|
||||
Task<BudgetStatus> GetBudgetStatusAsync(Guid scanId, CancellationToken ct);
|
||||
Task<PruneResult> PruneToFitAsync(Guid scanId, long targetBytes, CancellationToken ct);
|
||||
}
|
||||
|
||||
@@ -26,10 +27,11 @@ public sealed class EvidenceBudgetService : IEvidenceBudgetService
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public BudgetCheckResult CheckBudget(Guid scanId, EvidenceItem item)
|
||||
public async Task<BudgetCheckResult> CheckBudgetAsync(Guid scanId, EvidenceItem item, CancellationToken ct)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
var budget = _options.CurrentValue;
|
||||
var currentUsage = GetCurrentUsage(scanId);
|
||||
var currentUsage = await GetCurrentUsageAsync(scanId, ct);
|
||||
|
||||
var issues = new List<string>();
|
||||
|
||||
@@ -37,7 +39,9 @@ public sealed class EvidenceBudgetService : IEvidenceBudgetService
|
||||
var projectedTotal = currentUsage.TotalBytes + item.SizeBytes;
|
||||
if (projectedTotal > budget.MaxScanSizeBytes)
|
||||
{
|
||||
issues.Add($"Would exceed total budget: {projectedTotal:N0} > {budget.MaxScanSizeBytes:N0} bytes");
|
||||
issues.Add(
|
||||
$"Would exceed total budget: {projectedTotal.ToString("N0", CultureInfo.InvariantCulture)} > " +
|
||||
$"{budget.MaxScanSizeBytes.ToString("N0", CultureInfo.InvariantCulture)} bytes");
|
||||
}
|
||||
|
||||
// Check per-type budget
|
||||
@@ -47,7 +51,9 @@ public sealed class EvidenceBudgetService : IEvidenceBudgetService
|
||||
var projectedType = typeUsage + item.SizeBytes;
|
||||
if (projectedType > typeLimit)
|
||||
{
|
||||
issues.Add($"Would exceed {item.Type} budget: {projectedType:N0} > {typeLimit:N0} bytes");
|
||||
issues.Add(
|
||||
$"Would exceed {item.Type} budget: {projectedType.ToString("N0", CultureInfo.InvariantCulture)} > " +
|
||||
$"{typeLimit.ToString("N0", CultureInfo.InvariantCulture)} bytes");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +72,10 @@ public sealed class EvidenceBudgetService : IEvidenceBudgetService
|
||||
};
|
||||
}
|
||||
|
||||
public BudgetStatus GetBudgetStatus(Guid scanId)
|
||||
public async Task<BudgetStatus> GetBudgetStatusAsync(Guid scanId, CancellationToken ct)
|
||||
{
|
||||
var budget = _options.CurrentValue;
|
||||
var usage = GetCurrentUsage(scanId);
|
||||
var usage = await GetCurrentUsageAsync(scanId, ct);
|
||||
|
||||
return new BudgetStatus
|
||||
{
|
||||
@@ -92,13 +98,10 @@ public sealed class EvidenceBudgetService : IEvidenceBudgetService
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<PruneResult> PruneToFitAsync(
|
||||
Guid scanId,
|
||||
long targetBytes,
|
||||
CancellationToken ct)
|
||||
public async Task<PruneResult> PruneToFitAsync(Guid scanId, long targetBytes, CancellationToken ct)
|
||||
{
|
||||
var budget = _options.CurrentValue;
|
||||
var usage = GetCurrentUsage(scanId);
|
||||
var usage = await GetCurrentUsageAsync(scanId, ct);
|
||||
|
||||
if (usage.TotalBytes <= targetBytes)
|
||||
{
|
||||
@@ -113,6 +116,8 @@ public sealed class EvidenceBudgetService : IEvidenceBudgetService
|
||||
var candidates = items
|
||||
.Where(i => !budget.AlwaysPreserve.Contains(i.Type))
|
||||
.OrderBy(i => GetPrunePriority(i))
|
||||
.ThenBy(i => i.CreatedAt.UtcDateTime.Ticks)
|
||||
.ThenBy(i => i.Id)
|
||||
.ToList();
|
||||
|
||||
long prunedBytes = 0;
|
||||
@@ -158,15 +163,15 @@ public sealed class EvidenceBudgetService : IEvidenceBudgetService
|
||||
};
|
||||
}
|
||||
|
||||
private UsageStats GetCurrentUsage(Guid scanId)
|
||||
private async Task<UsageStats> GetCurrentUsageAsync(Guid scanId, CancellationToken ct)
|
||||
{
|
||||
// Implementation to calculate current usage from repository
|
||||
var items = _repository.GetByScanIdAsync(scanId, CancellationToken.None)
|
||||
.GetAwaiter().GetResult();
|
||||
var items = await _repository.GetByScanIdAsync(scanId, ct);
|
||||
|
||||
var totalBytes = items.Sum(i => i.SizeBytes);
|
||||
var byType = items
|
||||
.GroupBy(i => i.Type)
|
||||
.OrderBy(g => g.Key)
|
||||
.ToDictionary(g => g.Key, g => g.Sum(i => i.SizeBytes));
|
||||
|
||||
return new UsageStats
|
||||
|
||||
Reference in New Issue
Block a user