< Summary

Information
Class: Services.SearchServices.OrderSearch.OrderSearchIncrementalSyncJob
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/SearchServices/OrderSearch/OrderSearchIncrementalSyncJob.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 42
Coverable lines: 42
Total lines: 100
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 18
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
ExecuteAsync()0%272160%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/SearchServices/OrderSearch/OrderSearchIncrementalSyncJob.cs

#LineLine coverage
 1using Hangfire;
 2using Microsoft.EntityFrameworkCore;
 3using OzonDomains.Models;
 4using OzonRepositories.Context;
 5using Services.SignalRServices;
 6using Services.HangfireService;
 7
 8namespace Services.SearchServices.OrderSearch;
 9
 10/// <summary>
 11/// Раз в минуту докатывает в Elasticsearch заказы, изменённые с последнего checkpoint'а
 12/// (Order.UpdatedAt, проставляется BEFORE-триггером trg_orders_before_write_updatedat на
 13/// каждую запись независимо от C#-пути) — гарантия актуальности индекса для любого пути записи.
 14/// </summary>
 15public class OrderSearchIncrementalSyncJob
 16{
 17    public const string JobId = "OrderSearchIncrementalSyncJob";
 18    public const string DefaultCron = "* * * * *";
 19    public const string QueueName = HangfireQueueNames.OrderSearch;
 20    private const int BatchSize = 500;
 21    // Один минутный тик не должен бесконечно держать соединение с ST2 при большом backlog.
 22    // Следующий тик продолжит с сохранённого checkpoint.
 23    private const int MaxBatchesPerRun = 10;
 24    private const int NotificationBatchThreshold = 1_000;
 25
 26    private readonly ApplicationDbContext _context;
 27    private readonly IOrderSearchSyncService _syncService;
 28    private readonly IOrderSearchDiagnosticsStore _diagnostics;
 29
 030    public OrderSearchIncrementalSyncJob(
 031        ApplicationDbContext context,
 032        IOrderSearchSyncService syncService,
 033        IOrderSearchDiagnosticsStore diagnostics)
 34    {
 035        _context = context;
 036        _syncService = syncService;
 037        _diagnostics = diagnostics;
 038    }
 39
 40    [Queue(QueueName)]
 41    public async Task<string> ExecuteAsync()
 42    {
 043        var state = await _context.OrderSearchSyncStates.FindAsync(1);
 044        var isNew = state == null;
 045        state ??= new OrderSearchSyncState { Id = 1 };
 46
 047        var sinceUtc = state.LastSyncedAt ?? DateTime.MinValue;
 048        var sinceOrderId = state.LastSyncedOrderId;
 049        var syncedAny = false;
 050        var startedAt = DateTime.UtcNow;
 51
 052        for (var batchNumber = 0; batchNumber < MaxBatchesPerRun; batchNumber++)
 53        {
 054            var newCheckpoint = await _syncService.SyncBatchAsync(sinceUtc, sinceOrderId, BatchSize);
 055            if (newCheckpoint == null)
 56            {
 57                break;
 58            }
 59
 060            sinceUtc = newCheckpoint.UpdatedAt;
 061            sinceOrderId = newCheckpoint.OrderId;
 062            syncedAny = true;
 63        }
 64
 065        if (syncedAny)
 66        {
 067            state.LastSyncedAt = sinceUtc;
 068            state.LastSyncedOrderId = sinceOrderId;
 69        }
 70
 071        if (isNew)
 72        {
 073            _context.OrderSearchSyncStates.Add(state);
 74        }
 75
 076        await _context.SaveChangesAsync();
 77
 078        if (syncedAny)
 79        {
 080            var events = _diagnostics.GetIndexEvents(100)
 081                .Where(e => e.Operation == OrderSearchIndexOperation.IncrementalBatch && e.TimestampUtc >= startedAt)
 082                .ToList();
 083            var totalCount = events.Sum(e => e.Count);
 084            var totalMs = events.Sum(e => e.DurationMs);
 085            if (totalCount >= NotificationBatchThreshold)
 86            {
 87                try
 88                {
 089                    await NotificationService.NotifyAsync(
 090                        "ES Индекс", "#8B5CF6",
 091                        $"ES синк: обновлено {totalCount:N0} заказов за {totalMs:N0} мс",
 092                        "fa-bolt");
 093                }
 094                catch { /* не роняем джоб */ }
 95            }
 96        }
 97
 098        return $"OrderSearch incremental sync completed. Checkpoint: ({state.LastSyncedAt:O}, {state.LastSyncedOrderId})
 099    }
 100}