DET-004: Refactor Policy Gates for determinism
- EarnedCapacityEvaluator: inject TimeProvider - BudgetThresholdNotifier: inject TimeProvider Replace DateTimeOffset.UtcNow with _timeProvider.GetUtcNow() Sprint: SPRINT_20260104_001_BE_determinism_timeprovider_injection
This commit is contained in:
@@ -18,6 +18,7 @@ public sealed class BudgetThresholdNotifier
|
||||
{
|
||||
private readonly INotifyEventPublisher _publisher;
|
||||
private readonly ILogger<BudgetThresholdNotifier> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Thresholds for different budget status levels.
|
||||
@@ -37,10 +38,12 @@ public sealed class BudgetThresholdNotifier
|
||||
/// </summary>
|
||||
public BudgetThresholdNotifier(
|
||||
INotifyEventPublisher publisher,
|
||||
ILogger<BudgetThresholdNotifier> logger)
|
||||
ILogger<BudgetThresholdNotifier> logger,
|
||||
TimeProvider? timeProvider = null)
|
||||
{
|
||||
_publisher = publisher ?? throw new ArgumentNullException(nameof(publisher));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -73,7 +76,7 @@ public sealed class BudgetThresholdNotifier
|
||||
{
|
||||
if (budget.Status >= BudgetStatus.Yellow)
|
||||
{
|
||||
var payload = CreatePayload(budget, "warning");
|
||||
var payload = CreatePayload(budget, "warning", _timeProvider);
|
||||
await _publisher.PublishAsync(
|
||||
BudgetEventKinds.PolicyBudgetWarning,
|
||||
tenantId,
|
||||
@@ -95,7 +98,7 @@ public sealed class BudgetThresholdNotifier
|
||||
string tenantId,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var payload = CreatePayload(budget, "exceeded");
|
||||
var payload = CreatePayload(budget, "exceeded", _timeProvider);
|
||||
await _publisher.PublishAsync(
|
||||
BudgetEventKinds.PolicyBudgetExceeded,
|
||||
tenantId,
|
||||
@@ -118,7 +121,7 @@ public sealed class BudgetThresholdNotifier
|
||||
? BudgetEventKinds.PolicyBudgetExceeded
|
||||
: BudgetEventKinds.PolicyBudgetWarning;
|
||||
|
||||
var payload = CreatePayload(after, after.Status.ToString().ToLowerInvariant());
|
||||
var payload = CreatePayload(after, after.Status.ToString().ToLowerInvariant(), _timeProvider);
|
||||
payload["previousStatus"] = before.Status.ToString().ToLowerInvariant();
|
||||
|
||||
await _publisher.PublishAsync(eventKind, tenantId, payload, ct);
|
||||
@@ -130,7 +133,7 @@ public sealed class BudgetThresholdNotifier
|
||||
after.Status);
|
||||
}
|
||||
|
||||
private static JsonObject CreatePayload(RiskBudget budget, string severity)
|
||||
private static JsonObject CreatePayload(RiskBudget budget, string severity, TimeProvider timeProvider)
|
||||
{
|
||||
return new JsonObject
|
||||
{
|
||||
@@ -144,7 +147,7 @@ public sealed class BudgetThresholdNotifier
|
||||
["percentageUsed"] = budget.PercentageUsed,
|
||||
["status"] = budget.Status.ToString().ToLowerInvariant(),
|
||||
["severity"] = severity,
|
||||
["timestamp"] = DateTimeOffset.UtcNow.ToString("O")
|
||||
["timestamp"] = timeProvider.GetUtcNow().ToString("O")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ public sealed class EarnedCapacityEvaluator
|
||||
private readonly IPerformanceMetricsStore _metricsStore;
|
||||
private readonly IBudgetStore _budgetStore;
|
||||
private readonly EarnedCapacityOptions _options;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new earned capacity evaluator.
|
||||
@@ -23,11 +24,13 @@ public sealed class EarnedCapacityEvaluator
|
||||
public EarnedCapacityEvaluator(
|
||||
IPerformanceMetricsStore metricsStore,
|
||||
IBudgetStore budgetStore,
|
||||
EarnedCapacityOptions? options = null)
|
||||
EarnedCapacityOptions? options = null,
|
||||
TimeProvider? timeProvider = null)
|
||||
{
|
||||
_metricsStore = metricsStore ?? throw new ArgumentNullException(nameof(metricsStore));
|
||||
_budgetStore = budgetStore ?? throw new ArgumentNullException(nameof(budgetStore));
|
||||
_options = options ?? new EarnedCapacityOptions();
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -116,7 +119,7 @@ public sealed class EarnedCapacityEvaluator
|
||||
var updatedBudget = budget with
|
||||
{
|
||||
Allocated = budget.Allocated + additionalPoints,
|
||||
UpdatedAt = DateTimeOffset.UtcNow
|
||||
UpdatedAt = _timeProvider.GetUtcNow()
|
||||
};
|
||||
|
||||
await _budgetStore.UpdateAsync(updatedBudget, ct);
|
||||
|
||||
Reference in New Issue
Block a user