AVS-Carton-Shipment-Verifier/Services/SqliteScanHistoryStore.cs

91 lines
3.0 KiB
C#

using AVSCartonShipmentVerifier.DTOs;
using AVSCartonShipmentVerifier.Configuration;
using AVSCartonShipmentVerifier.ScanHistory;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace AVSCartonShipmentVerifier.Services;
public sealed class SqliteScanHistoryStore(
ScanHistoryDbContext dbContext,
IOptions<ScanHistoryOptions> options,
ILogger<SqliteScanHistoryStore> logger) : IScanHistoryStore
{
private readonly ScanHistoryDbContext _dbContext = dbContext;
private readonly ScanHistoryOptions _options = options.Value;
private readonly ILogger<SqliteScanHistoryStore> _logger = logger;
public async Task AddAsync(ScannedRecordDto record, CancellationToken cancellationToken = default)
{
try
{
_dbContext.ScanHistoryEntries.Add(new ScanHistoryEntry
{
ModelNumber = record.ModelNumber,
UniqueNumber = record.UniqueNumber,
ExistsInSystem = record.ExistsInSystem,
ShipmentMarked = record.ShipmentMarked,
ProcessedAtUtc = record.ProcessedAtUtc
});
await _dbContext.SaveChangesAsync(cancellationToken);
await TrimOldRecordsAsync(cancellationToken);
}
catch (Exception exception)
{
_logger.LogError(exception, "Failed to persist scan history entry.");
}
}
public async Task<IReadOnlyCollection<ScannedRecordDto>> GetLastFiveAsync(CancellationToken cancellationToken = default)
{
try
{
var entries = await _dbContext.ScanHistoryEntries
.AsNoTracking()
.OrderByDescending(x => x.ProcessedAtUtc)
.Take(5)
.ToArrayAsync(cancellationToken);
return entries
.Select(x => new ScannedRecordDto
{
ModelNumber = x.ModelNumber,
UniqueNumber = x.UniqueNumber,
ExistsInSystem = x.ExistsInSystem,
ShipmentMarked = x.ShipmentMarked,
ProcessedAtUtc = DateTime.SpecifyKind(x.ProcessedAtUtc, DateTimeKind.Utc)
})
.ToArray();
}
catch (Exception exception)
{
_logger.LogError(exception, "Failed to read scan history.");
return Array.Empty<ScannedRecordDto>();
}
}
private async Task TrimOldRecordsAsync(CancellationToken cancellationToken)
{
var max = _options.MaxRecordsToKeep;
if (max <= 0)
{
return;
}
var toDelete = await _dbContext.ScanHistoryEntries
.OrderByDescending(x => x.ProcessedAtUtc)
.Skip(max)
.Select(x => x.Id)
.ToArrayAsync(cancellationToken);
if (toDelete.Length == 0)
{
return;
}
_dbContext.ScanHistoryEntries.RemoveRange(toDelete.Select(id => new ScanHistoryEntry { Id = id }));
await _dbContext.SaveChangesAsync(cancellationToken);
}
}