diff --git a/backend/Tnsu.ApprovalRoute.Application/Reminders/ReminderService.cs b/backend/Tnsu.ApprovalRoute.Application/Reminders/ReminderService.cs index 9fea9c6..1a62dc5 100644 --- a/backend/Tnsu.ApprovalRoute.Application/Reminders/ReminderService.cs +++ b/backend/Tnsu.ApprovalRoute.Application/Reminders/ReminderService.cs @@ -38,23 +38,28 @@ public sealed class ReminderService( .Where(x => x.SlaHours != null && x.ListId != null && x.SiteUrl != null) .ToListAsync(cancellationToken); - var reminders = new List(); + // Типы независимы (разные сайты/списки в SharePoint) — их обход + // распараллелен, иначе время растёт линейно с числом типов: каждый тип + // сам по себе делает несколько последовательных HTTP-запросов. + var results = await Task.WhenAll(types.Select(type => GetOverdueForTypeSafeAsync(type, now, cancellationToken))); - foreach (var type in types) + return Result.Ok>(results.SelectMany(r => r).ToList()); + } + + private async Task> GetOverdueForTypeSafeAsync( + RequestType type, DateTimeOffset now, CancellationToken cancellationToken) + { + try { - try - { - reminders.AddRange(await GetOverdueForTypeAsync(type, now, cancellationToken)); - } - catch (Exception e) - { - // Недоступный список одного типа не должен обнулять напоминания по - // всем остальным: Power Automate получит то, что удалось собрать. - logger.LogError(e, "Напоминания по типу заявки «{Type}» не собраны", type.Name); - } + return await GetOverdueForTypeAsync(type, now, cancellationToken); + } + catch (Exception e) + { + // Недоступный список одного типа не должен обнулять напоминания по + // всем остальным: Power Automate получит то, что удалось собрать. + logger.LogError(e, "Напоминания по типу заявки «{Type}» не собраны", type.Name); + return []; } - - return Result.Ok>(reminders); } private async Task> GetOverdueForTypeAsync(