more audit work
This commit is contained in:
23
src/__Libraries/StellaOps.HybridLogicalClock/AGENTS.md
Normal file
23
src/__Libraries/StellaOps.HybridLogicalClock/AGENTS.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Hybrid Logical Clock Library Charter
|
||||
|
||||
## Mission
|
||||
Provide deterministic, monotonic HLC timestamps for distributed ordering.
|
||||
|
||||
## Responsibilities
|
||||
- Maintain HLC core logic, parsing, and serialization.
|
||||
- Ensure TimeProvider usage for deterministic tests.
|
||||
- Track sprint tasks in `TASKS.md` and update the sprint tracker.
|
||||
|
||||
## Key Paths
|
||||
- `HybridLogicalClock.cs`
|
||||
- `HlcTimestamp.cs`
|
||||
- `PostgresHlcStateStore.cs`
|
||||
|
||||
## Required Reading
|
||||
- `docs/modules/platform/architecture-overview.md`
|
||||
- `docs/implplan/permament/SPRINT_20251229_049_BE_csproj_audit_maint_tests.md`
|
||||
|
||||
## Working Agreement
|
||||
- 1. Keep timestamps monotonic and causally ordered.
|
||||
- 2. Use invariant parsing/formatting.
|
||||
- 3. Update `TASKS.md` and sprint statuses when work changes.
|
||||
@@ -275,11 +275,34 @@ public sealed class HybridLogicalClock : IHybridLogicalClock
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
private async Task PersistStateAsync(HlcTimestamp timestamp)
|
||||
private Task PersistStateAsync(HlcTimestamp timestamp)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _stateStore.SaveAsync(timestamp);
|
||||
var saveTask = _stateStore.SaveAsync(timestamp);
|
||||
if (saveTask.IsCompletedSuccessfully)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
return PersistStateAsyncSlow(saveTask, timestamp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
ex,
|
||||
"Failed to persist HLC state for node {NodeId}: {Timestamp}",
|
||||
_nodeId,
|
||||
timestamp);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PersistStateAsyncSlow(Task saveTask, HlcTimestamp timestamp)
|
||||
{
|
||||
try
|
||||
{
|
||||
await saveTask.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// Task: HLC-004 - Implement IHlcStateStore interface and InMemoryHlcStateStore
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace StellaOps.HybridLogicalClock;
|
||||
|
||||
/// <summary>
|
||||
@@ -17,7 +15,8 @@ namespace StellaOps.HybridLogicalClock;
|
||||
/// </remarks>
|
||||
public sealed class InMemoryHlcStateStore : IHlcStateStore
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, HlcTimestamp> _states = new(StringComparer.Ordinal);
|
||||
private readonly Dictionary<string, HlcTimestamp> _states = new(StringComparer.Ordinal);
|
||||
private readonly object _lock = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<HlcTimestamp?> LoadAsync(string nodeId, CancellationToken ct = default)
|
||||
@@ -25,10 +24,13 @@ public sealed class InMemoryHlcStateStore : IHlcStateStore
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(nodeId);
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
return Task.FromResult(
|
||||
_states.TryGetValue(nodeId, out var timestamp)
|
||||
? timestamp
|
||||
: (HlcTimestamp?)null);
|
||||
lock (_lock)
|
||||
{
|
||||
return Task.FromResult(
|
||||
_states.TryGetValue(nodeId, out var timestamp)
|
||||
? timestamp
|
||||
: (HlcTimestamp?)null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -36,14 +38,21 @@ public sealed class InMemoryHlcStateStore : IHlcStateStore
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
_states.AddOrUpdate(
|
||||
timestamp.NodeId,
|
||||
timestamp,
|
||||
(_, existing) =>
|
||||
lock (_lock)
|
||||
{
|
||||
if (_states.TryGetValue(timestamp.NodeId, out var existing))
|
||||
{
|
||||
// Only update if new timestamp is greater (maintain monotonicity)
|
||||
return timestamp > existing ? timestamp : existing;
|
||||
});
|
||||
if (timestamp > existing)
|
||||
{
|
||||
_states[timestamp.NodeId] = timestamp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_states[timestamp.NodeId] = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -52,10 +61,24 @@ public sealed class InMemoryHlcStateStore : IHlcStateStore
|
||||
/// Gets all stored states (for testing/debugging).
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, HlcTimestamp> GetAllStates() =>
|
||||
new Dictionary<string, HlcTimestamp>(_states);
|
||||
GetAllStatesSnapshot();
|
||||
|
||||
/// <summary>
|
||||
/// Clears all stored states (for testing).
|
||||
/// </summary>
|
||||
public void Clear() => _states.Clear();
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_states.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private IReadOnlyDictionary<string, HlcTimestamp> GetAllStatesSnapshot()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return new Dictionary<string, HlcTimestamp>(_states);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
src/__Libraries/StellaOps.HybridLogicalClock/TASKS.md
Normal file
10
src/__Libraries/StellaOps.HybridLogicalClock/TASKS.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Hybrid Logical Clock Task Board
|
||||
|
||||
This board mirrors active sprint tasks for this module.
|
||||
Source of truth: `docs/implplan/permament/SPRINT_20251229_049_BE_csproj_audit_maint_tests.md`.
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| AUDIT-0087-M | DONE | Revalidated 2026-01-08; open findings tracked in audit report. |
|
||||
| AUDIT-0087-T | DONE | Revalidated 2026-01-08; open findings tracked in audit report. |
|
||||
| AUDIT-0087-A | TODO | Revalidated 2026-01-08 (open findings). |
|
||||
Reference in New Issue
Block a user