73 lines
2.6 KiB
C#
73 lines
2.6 KiB
C#
|
|
using StellaOps.PacksRegistry.Core.Contracts;
|
|
using StellaOps.PacksRegistry.Core.Models;
|
|
using System.Text.Json;
|
|
|
|
namespace StellaOps.PacksRegistry.Infrastructure.FileSystem;
|
|
|
|
public sealed class FileAuditRepository : IAuditRepository
|
|
{
|
|
private readonly string _path;
|
|
private readonly JsonSerializerOptions _jsonOptions;
|
|
private readonly SemaphoreSlim _mutex = new(1, 1);
|
|
|
|
public FileAuditRepository(string rootPath)
|
|
{
|
|
var root = string.IsNullOrWhiteSpace(rootPath) ? Path.GetFullPath("data/packs") : Path.GetFullPath(rootPath);
|
|
Directory.CreateDirectory(root);
|
|
_path = Path.Combine(root, "audit.ndjson");
|
|
_jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
|
|
}
|
|
|
|
public async Task AppendAsync(AuditRecord record, CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(record);
|
|
await _mutex.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
try
|
|
{
|
|
await using var stream = new FileStream(_path, FileMode.Append, FileAccess.Write, FileShare.Read);
|
|
await using var writer = new StreamWriter(stream);
|
|
var json = JsonSerializer.Serialize(record, _jsonOptions);
|
|
await writer.WriteLineAsync(json.AsMemory(), cancellationToken).ConfigureAwait(false);
|
|
}
|
|
finally
|
|
{
|
|
_mutex.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<IReadOnlyList<AuditRecord>> ListAsync(string? tenantId = null, CancellationToken cancellationToken = default)
|
|
{
|
|
if (!File.Exists(_path))
|
|
{
|
|
return Array.Empty<AuditRecord>();
|
|
}
|
|
|
|
await _mutex.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
try
|
|
{
|
|
var lines = await File.ReadAllLinesAsync(_path, cancellationToken).ConfigureAwait(false);
|
|
IEnumerable<AuditRecord> records = lines
|
|
.Where(l => !string.IsNullOrWhiteSpace(l))
|
|
.Select(l => JsonSerializer.Deserialize<AuditRecord>(l, _jsonOptions))
|
|
.Where(r => r is not null)!
|
|
.Cast<AuditRecord>();
|
|
|
|
if (!string.IsNullOrWhiteSpace(tenantId))
|
|
{
|
|
records = records.Where(r => string.Equals(r.TenantId, tenantId, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
return records
|
|
.OrderBy(r => r.OccurredAtUtc)
|
|
.ThenBy(r => r.PackId, StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
}
|
|
finally
|
|
{
|
|
_mutex.Release();
|
|
}
|
|
}
|
|
}
|
|
|