using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using PARR.BLL.Helpers; using PARR.Core.Common.Interfaces.RabbitServices; using PARR.Core.Repositories.Interfaces; using PARR.Core.Repositories.Interfaces.Schedule; using PARR.Core.Services.NextRunServices; using PARR.Domain.Entities; using PARR.Domain.Entities.Base.History; using PARR.Domain.Enums; using PARR.Domain.Settings; using PARR.EsppScheduleSync.Domain; using PARR.EsppScheduleSync.Settings; using PARR.EsppSync; using PARR.EsppSync.Helpers; namespace PARR.EsppScheduleSync { internal class ScheduleSyncher : IScheduleSyncher { private readonly ILogger logger; private readonly GlobalSettings globalSettings; private readonly IRabbitService mqService; private readonly ISyncService syncService; private readonly SettingsFromDb settingsFromDb; private readonly IServiceProvider serviceProvider; private string noneExcludeCalendarEsppValue; public ScheduleSyncher( ILogger logger, GlobalSettings globalSettings, IRabbitService mqService, ISyncService syncService, SettingsFromDb settingsFromDb, IServiceProvider serviceProvider ) { this.logger = logger; this.globalSettings = globalSettings; this.mqService = mqService; this.syncService = syncService; this.settingsFromDb = settingsFromDb; this.serviceProvider = serviceProvider; this.noneExcludeCalendarEsppValue = string.Empty; if (globalSettings.MqSettings == null) { logger.LogError("Нет секции настроек хранилища. MqSettings, EsppTemplates"); throw new Exception("Нет секции настроек хранилища. MqSettings, EsppTemplates"); } if (string.IsNullOrEmpty(globalSettings.ParsingSeparator)) throw new ArgumentException("ParsingSeparator не задан в GlobalSettings."); } public async Task StartAsync() { if (string.IsNullOrEmpty(noneExcludeCalendarEsppValue)) await GetNoneExcludeCalendarEsppValueAsync(); var isConnected = await mqService.InitConsumerAsync(globalSettings!.MqSettings!, SyncScheduleAsync); if (!isConnected) throw new Exception("Ошибка при подключении к RabbitMq"); logger.LogInformation("Запущена проверка очереди {QueueName}.", globalSettings.MqSettings!.QueueName); } public async Task StopAsync() { await mqService.DisposeAsync(); logger.LogInformation("=== === === Соединение с очередью {QueueName} закрыто === === ===", globalSettings.MqSettings!.QueueName); } /// /// Получение типа исключения /// /// /// private async Task GetNoneExcludeCalendarEsppValueAsync() { using var scope = serviceProvider.CreateScope(); var service = scope.ServiceProvider.GetRequiredService(); var noneExcludeType = await service.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Code == nameof(ScheduleExcludeTypeEnum.None)); if (noneExcludeType == null) throw new InvalidOperationException($"Не найден тип исключения с кодом '{nameof(ScheduleExcludeTypeEnum.None)}'"); noneExcludeCalendarEsppValue = noneExcludeType.EsppValue; } /// /// Старт синхронизации, получили сообщение /// /// /// private async Task SyncScheduleAsync(string str) { await syncService.SyncEsppObjectAsync(str, ParseStrToEsppObject, ConvertDbObjToEsppObj, CustomComparisionCheckAsyncHandler, AfterParseStringToEsppObjectAsyncHandler); } /// /// Выполняется после парсинга строки в объект ЕСПП. /// Проверка, есть ли у расписания шаблон. Если имена шаблона и расписания не совпадают, установить шаблону статус обновления. /// /// /// /// private async Task AfterParseStringToEsppObjectAsyncHandler(EsppObjectSchedule esppObject) { var esppScheduleId = esppObject.Code; var esppTemplateName = esppObject.TemplateName; using var scope = serviceProvider.CreateScope(); var templateService = scope.ServiceProvider.GetRequiredService(); // это не очень, так как esppScheduleId может быть null или empty, а в БД таких значений может быть много //var candidates = await templateService.Get() // .Include(t => t.RobotConfigurations) // .Where(t => t.Name == esppTemplateName || t.ScheduleEsppId == esppScheduleId) // .ToListAsync(); IQueryable