95 lines
4.5 KiB
C#
95 lines
4.5 KiB
C#
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Logging;
|
||
using PARR.Core.Repositories.Interfaces;
|
||
using PARR.Core.Repositories.Interfaces.RobotRepositories;
|
||
using PARR.Core.Services.Snapshots.Interfaces;
|
||
using PARR.Domain.Entities.RobotEntities;
|
||
using PARR.Domain.Exceptions;
|
||
|
||
namespace PARR.Core.Services.Snapshots.Implementations
|
||
{
|
||
/// <summary>
|
||
/// Снапшоты для таблицы RobotConfiguration
|
||
/// </summary>
|
||
internal class RobotConfigurationSnapshotService : ISnapshotProvider
|
||
{
|
||
private readonly IRobotConfigurationRepository _robotConfigurationRepository;
|
||
private readonly IRobotConfigurationSnapshotRepository _robotConfigurationSnapshotRepository;
|
||
private readonly ILogger<RobotConfigurationSnapshotService> _logger;
|
||
private readonly ISnapshotSettings _snapshotSettings;
|
||
|
||
public TimeSpan Interval => _snapshotSettings.RobotConfigurationSnapshotInterval;// TimeSpan.FromMinutes(2);
|
||
|
||
public TimeSpan RetentionPeriod => _snapshotSettings.RobotConfigurationSnapshotRetentionPeriod;//TimeSpan.FromDays(60);
|
||
|
||
public RobotConfigurationSnapshotService(
|
||
IRobotConfigurationRepository robotConfigurationRepository,
|
||
IRobotConfigurationSnapshotRepository robotConfigurationSnapshotRepository,
|
||
ILogger<RobotConfigurationSnapshotService> logger,
|
||
ISnapshotSettings snapshotSettings
|
||
)
|
||
{
|
||
_robotConfigurationRepository = robotConfigurationRepository;
|
||
_robotConfigurationSnapshotRepository = robotConfigurationSnapshotRepository;
|
||
_logger = logger;
|
||
_snapshotSettings = snapshotSettings;
|
||
}
|
||
|
||
|
||
public async Task TakeSnapshotAsync(CancellationToken cancellationToken)
|
||
{
|
||
var now = DateTimeOffset.UtcNow;
|
||
|
||
_logger.LogDebug("Сбор метрик для снапшота RobotConfigurations...");
|
||
|
||
var stats = await _robotConfigurationRepository.Get()
|
||
.GroupBy(t => new { t.RobotCode, t.RobotStatusCode, t.TaskStatusCode })
|
||
.Select(g => new
|
||
{
|
||
g.Key.RobotCode,
|
||
g.Key.RobotStatusCode,
|
||
g.Key.TaskStatusCode,
|
||
Count = g.Count()
|
||
})
|
||
.ToListAsync(cancellationToken);
|
||
|
||
if (!stats.Any())
|
||
{
|
||
_logger.LogDebug("Нет активных заданий роботов для создания снапшота.");
|
||
return;
|
||
}
|
||
|
||
var snapshots = stats.Select(s => new RobotConfigurationSnapshot
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
DateCreated = now,
|
||
RobotCode = s.RobotCode,
|
||
RobotStatusCode = s.RobotStatusCode,
|
||
TaskStatusCode = s.TaskStatusCode,
|
||
Count = s.Count
|
||
}).ToList();
|
||
|
||
if (!await _robotConfigurationSnapshotRepository.AddRangeAsync(snapshots) || !await _robotConfigurationSnapshotRepository.CommitAsync())
|
||
throw new DbErrorException("Ошибка при сохранении в БД");
|
||
|
||
_logger.LogInformation("Успешно сохранен снапшот RobotConfigurations. Записано строк: {Count}. Периодичность: {Interval}", snapshots.Count, Interval);
|
||
}
|
||
|
||
|
||
public async Task CleanUpOldSnapshotsAsync(CancellationToken cancellationToken)
|
||
{
|
||
// Вычисляем граничную дату (всё, что было ДО нее — удаляем)
|
||
var thresholdDate = DateTimeOffset.UtcNow.Subtract(RetentionPeriod);
|
||
|
||
_logger.LogInformation("[{ServiceName}] Запуск очистки старых снапшотов. Удаление данных старше {ThresholdDate}", GetType().Name, thresholdDate);
|
||
|
||
// Фильтруем старые записи и вызываем ExecuteDeleteAsync для удаления прямо в базе данных
|
||
var deletedCount = await _robotConfigurationSnapshotRepository.Get()
|
||
.Where(s => s.DateCreated < thresholdDate)
|
||
.ExecuteDeleteAsync(cancellationToken);
|
||
|
||
_logger.LogInformation("[{ServiceName}] Очистка завершена. Удалено устаревших строк снапшотов: {Count}", GetType().Name, deletedCount);
|
||
}
|
||
}
|
||
}
|