using System.Threading.Channels;
using ROLAC.API.Entities.Logging;
namespace ROLAC.API.Services.Logging;
///
/// A singleton, bounded in-memory queue decoupling log producers (the ILogger hot path, the
/// audit interceptor, singleton services) from the single background DB writer. Enqueue is a
/// non-blocking TryWrite; when full the OLDEST entry is dropped (DropWrite) rather than
/// blocking a request thread or throwing — logging must never throw or stall business code.
/// Carries both SystemLog and AuditLog rows via a small union envelope.
///
public sealed class SystemLogQueue
{
private readonly Channel _channel =
Channel.CreateBounded(new BoundedChannelOptions(capacity: 4096)
{
FullMode = BoundedChannelFullMode.DropWrite,
SingleReader = true,
SingleWriter = false,
});
public bool TryEnqueue(SystemLog log) => _channel.Writer.TryWrite(new LogEnvelope(log, null));
public bool TryEnqueue(AuditLog log) => _channel.Writer.TryWrite(new LogEnvelope(null, log));
public IAsyncEnumerable ReadAllAsync(CancellationToken cancellationToken) =>
_channel.Reader.ReadAllAsync(cancellationToken);
}
/// Either a SystemLog or an AuditLog — exactly one is non-null.
public sealed record LogEnvelope(SystemLog? System, AuditLog? Audit);