DET-004: Refactor Policy BudgetLedger for determinism

- Inject TimeProvider and IGuidProvider in BudgetLedger constructor
- Replace DateTimeOffset.UtcNow with _timeProvider.GetUtcNow()
- Replace Guid.NewGuid() with _guidProvider.NewGuid()
- Add Determinism.Abstractions reference to Policy csproj

Sprint: SPRINT_20260104_001_BE_determinism_timeprovider_injection
Task: DET-004 (in progress - Policy module)
This commit is contained in:
StellaOps Bot
2026-01-04 12:38:35 +02:00
parent cb898a4ac8
commit 8e0cc71b2e
2 changed files with 18 additions and 8 deletions

View File

@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Determinism;
namespace StellaOps.Policy.Gates;
@@ -10,10 +11,18 @@ public sealed class BudgetLedger : IBudgetLedger
{
private readonly IBudgetStore _store;
private readonly ILogger<BudgetLedger> _logger;
private readonly TimeProvider _timeProvider;
private readonly IGuidProvider _guidProvider;
public BudgetLedger(IBudgetStore store, ILogger<BudgetLedger>? logger = null)
public BudgetLedger(
IBudgetStore store,
TimeProvider? timeProvider = null,
IGuidProvider? guidProvider = null,
ILogger<BudgetLedger>? logger = null)
{
_store = store ?? throw new ArgumentNullException(nameof(store));
_timeProvider = timeProvider ?? TimeProvider.System;
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
_logger = logger ?? NullLogger<BudgetLedger>.Instance;
}
@@ -64,12 +73,12 @@ public sealed class BudgetLedger : IBudgetLedger
// Record the consumption
var entry = new BudgetEntry
{
EntryId = Guid.NewGuid().ToString(),
EntryId = _guidProvider.NewGuid().ToString(),
ServiceId = serviceId,
Window = budget.Window,
ReleaseId = releaseId,
RiskPoints = riskPoints,
ConsumedAt = DateTimeOffset.UtcNow
ConsumedAt = _timeProvider.GetUtcNow()
};
await _store.AddEntryAsync(entry, ct).ConfigureAwait(false);
@@ -78,7 +87,7 @@ public sealed class BudgetLedger : IBudgetLedger
var updatedBudget = budget with
{
Consumed = budget.Consumed + riskPoints,
UpdatedAt = DateTimeOffset.UtcNow
UpdatedAt = _timeProvider.GetUtcNow()
};
await _store.UpdateAsync(updatedBudget, ct).ConfigureAwait(false);
@@ -122,7 +131,7 @@ public sealed class BudgetLedger : IBudgetLedger
var updatedBudget = budget with
{
Allocated = newAllocation,
UpdatedAt = DateTimeOffset.UtcNow
UpdatedAt = _timeProvider.GetUtcNow()
};
await _store.UpdateAsync(updatedBudget, ct).ConfigureAwait(false);
@@ -148,15 +157,15 @@ public sealed class BudgetLedger : IBudgetLedger
Window = window,
Allocated = DefaultBudgetAllocations.GetMonthlyAllocation(tier),
Consumed = 0,
UpdatedAt = DateTimeOffset.UtcNow
UpdatedAt = _timeProvider.GetUtcNow()
};
await _store.CreateAsync(budget, ct).ConfigureAwait(false);
return budget;
}
private static string GetCurrentWindow() =>
DateTimeOffset.UtcNow.ToString("yyyy-MM");
private string GetCurrentWindow() =>
_timeProvider.GetUtcNow().ToString("yyyy-MM");
private Task<ServiceTier> GetServiceTierAsync(string serviceId, CancellationToken ct)
{

View File

@@ -28,5 +28,6 @@
<ProjectReference Include="../../../Attestor/__Libraries/StellaOps.Attestor.ProofChain/StellaOps.Attestor.ProofChain.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Canonical.Json/StellaOps.Canonical.Json.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography/StellaOps.Cryptography.csproj" />
<ProjectReference Include="../../../__Libraries/StellaOps.Determinism.Abstractions/StellaOps.Determinism.Abstractions.csproj" />
</ItemGroup>
</Project>