< Summary

Information
Class: Services.StockSyncServices.RunAllPresetsJob
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/StockSyncServices/RunAllPresetsJob.cs
Line coverage
100%
Covered lines: 38
Uncovered lines: 0
Coverable lines: 38
Total lines: 75
Line coverage: 100%
Branch coverage
87%
Covered branches: 14
Total branches: 16
Branch coverage: 87.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
ExecuteAsync()87.5%1616100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/StockSyncServices/RunAllPresetsJob.cs

#LineLine coverage
 1using Hangfire;
 2using Microsoft.Extensions.Logging;
 3using Services.BitrixStockServices;
 4using Services.HangfireService;
 5
 6namespace Services.StockSyncServices;
 7
 8/// <summary>
 9/// Последовательно запускает все сохранённые пресеты синхронизации остатков Ozon.
 10/// Цепочку этапов каждого пресета ведёт <see cref="IBitrixStockSyncPipelineOrchestrator"/> (тот же
 11/// компонент, что и UI-запуск), после чего отправляется письмо-отчёт. Последовательность пресетов
 12/// предотвращает превышение rate limit Ozon API.
 13/// </summary>
 1014public class RunAllPresetsJob(
 1015    IBitrixStockSyncPresetService presetService,
 1016    IBitrixStockSyncPipelineOrchestrator orchestrator,
 1017    SendSyncReportEmailJob emailJob,
 1018    ILogger<RunAllPresetsJob> logger)
 19{
 20    public const string QueueName = HangfireQueueNames.Main;
 21
 22    [Queue(QueueName)]
 23    [DisableConcurrentExecution(timeoutInSeconds: 0)]
 24    public async Task ExecuteAsync(CancellationToken cancellationToken = default)
 25    {
 1026        var presets = await presetService.GetAllAsync(cancellationToken);
 1127        if (presets.Count == 0) return;
 28
 4129        foreach (var preset in presets)
 30        {
 1231            cancellationToken.ThrowIfCancellationRequested();
 32
 1233            var jobId = Guid.NewGuid().ToString("N");
 1234            var reportId = jobId;
 1235            var orderedClientIds = preset.GetOrderedClientIds();
 36
 1237            var request = new BitrixStockSyncReportStartRequest
 1238            {
 1239                JobId = jobId,
 1240                OzonClientIds = orderedClientIds,
 1241                OzonClientId = orderedClientIds.FirstOrDefault(),
 1242                Article = preset.ArticleFilter,
 1243                SelectedStoreTitles = preset.SelectedStores,
 1244                DisabledWarehouseMappingIds = preset.DisabledWarehouseMappingIds is { Count: > 0 } disabledIds
 1245                    ? disabledIds
 1246                    : null,
 1247                StageSettings = preset.StageSettings
 1248            };
 49
 50            try
 51            {
 52                // rootJobId = null — без SignalR (фоновое расписание, не UI).
 1253                var pipelineResult = await orchestrator.RunPipelineAsync(reportId, request, rootJobId: null, cancellatio
 954                if (pipelineResult.Success)
 55                {
 756                    await emailJob.ExecuteAsync(reportId, preset.Name ?? "", cancellationToken);
 57                }
 58                else
 59                {
 260                    logger.LogInformation(
 261                        "Пресет {PresetName} (reportId={ReportId}) пропущен или завершился без успеха: {Error}",
 262                        preset.Name, reportId, pipelineResult.Error);
 63                }
 964            }
 165            catch (OperationCanceledException)
 66            {
 167                throw;
 68            }
 269            catch (Exception ex)
 70            {
 271                logger.LogError(ex, "Пресет {PresetName} (reportId={ReportId}) завершился с ошибкой", preset.Name, repor
 272            }
 1173        }
 974    }
 75}