using FrameworkBLL.AuditQuery; using FrameworkDAL.CustomCode.Archive; using GB5Shared.DTO.Framework.Login; using GB5Shared.QueryExecutor; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Threading; using System.Threading.Tasks; namespace FrameworkBLL.Archive { public sealed class EventLogArchiveBLL : IEventLogArchiveBLL { private readonly IEventLogArchiveDAL _dal; private readonly IQueryExecutor _qe; private readonly IOptions _settings; private readonly ILogger _logger; public EventLogArchiveBLL( IEventLogArchiveDAL dal, IQueryExecutor qe, IOptions settings, ILogger logger) { _dal = dal; _qe = qe; _settings = settings; _logger = logger; } public async Task ArchiveForTenantAsync(LoginDTO login, CancellationToken ct = default) { var retentionMonths = _settings.Value.RetentionMonths; var cutoffDate = DateTime.UtcNow.AddMonths(-retentionMonths); _logger.LogInformation( "EventLogArchive: starting for TenantId={TenantId} CutoffDate={CutoffDate} RetentionMonths={Months}", login.ClientId, cutoffDate, retentionMonths); // Stats before var (hotBefore, archiveBefore) = await _dal.GetStatsAsync(login, ct).ConfigureAwait(false); _logger.LogInformation( "EventLogArchive: before — hot={Hot} archive={Archive} TenantId={TenantId}", hotBefore, archiveBefore, login.ClientId); // Move + delete in a single transaction var tx = await _qe.BeginTransactionAsync(login).ConfigureAwait(false); try { await _dal.MoveToArchiveAsync(cutoffDate, login, tx, ct).ConfigureAwait(false); await _dal.DeleteHotRowsAsync(cutoffDate, login, tx, ct).ConfigureAwait(false); await _qe.CommitAsync(tx).ConfigureAwait(false); } catch { await _qe.RollbackAsync(tx).ConfigureAwait(false); throw; } // Stats after var (hotAfter, archiveAfter) = await _dal.GetStatsAsync(login, ct).ConfigureAwait(false); _logger.LogInformation( "EventLogArchive: done — hot={Hot} archive={Archive} moved={Moved} TenantId={TenantId}", hotAfter, archiveAfter, hotBefore - hotAfter, login.ClientId); } } }