diff --git a/backend/Tnsu.ApprovalRoute.Application/RequestManage/RequestManageService.cs b/backend/Tnsu.ApprovalRoute.Application/RequestManage/RequestManageService.cs index 3a988f7..fd9667b 100644 --- a/backend/Tnsu.ApprovalRoute.Application/RequestManage/RequestManageService.cs +++ b/backend/Tnsu.ApprovalRoute.Application/RequestManage/RequestManageService.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using System.Text.Json; using System.Text.RegularExpressions; using FluentResults; @@ -266,6 +267,29 @@ public sealed class RequestManageService( return result; } + // Пара «список согласования → (его заголовок, адрес парного списка данных)» + // не меняется, пока список не переименуют, — запоминаем на время жизни процесса, + // чтобы не тратить два запроса к SharePoint на каждый вызов. Ключ — адрес списка. + private static readonly ConcurrentDictionary ListPairs = + new(StringComparer.OrdinalIgnoreCase); + + private async Task<(string ApprovalTitle, string DataListUrl)?> ResolveListPairAsync( + string siteUrl, string approvalListUrl, CancellationToken cancellationToken) + { + if (ListPairs.TryGetValue(approvalListUrl, out var cached)) return cached; + + var approvalList = await sharePoint.GetListByUrlAsync(siteUrl, approvalListUrl, cancellationToken); + if (approvalList is null || !ApprovalListSuffix.IsMatch(approvalList.Title)) return null; + + var dataTitle = ApprovalListSuffix.Replace(approvalList.Title, " — данные"); + var dataList = await sharePoint.GetListByTitleAsync(siteUrl, dataTitle, cancellationToken); + if (dataList is null) return null; + + var pair = (approvalList.Title, dataList.ServerRelativeUrl); + ListPairs[approvalListUrl] = pair; + return pair; + } + private static string? ListUrlFromHitPath(string? path) { if (string.IsNullOrWhiteSpace(path) || !Uri.TryCreate(path, UriKind.Absolute, out var uri)) return null; @@ -287,18 +311,15 @@ public sealed class RequestManageService( { try { - var approvalList = await sharePoint.GetListByUrlAsync(siteUrl, approvalListUrl, cancellationToken); - if (approvalList is null || !ApprovalListSuffix.IsMatch(approvalList.Title)) return []; - - var dataTitle = ApprovalListSuffix.Replace(approvalList.Title, " — данные"); - var dataList = await sharePoint.GetListByTitleAsync(siteUrl, dataTitle, cancellationToken); - if (dataList is null) return []; + var pair = await ResolveListPairAsync(siteUrl, approvalListUrl, cancellationToken); + if (pair is null) return []; + var (approvalTitle, dataListUrl) = pair.Value; // Какому типу заявок принадлежит эта партиция (текущая или архивная). var requestType = siteTypes.FirstOrDefault(rt => - string.Equals(rt.ListId, dataList.ServerRelativeUrl, StringComparison.OrdinalIgnoreCase) + string.Equals(rt.ListId, dataListUrl, StringComparison.OrdinalIgnoreCase) || archivedByType[rt.Id].Any(a => - string.Equals(a.ListId, dataList.ServerRelativeUrl, StringComparison.OrdinalIgnoreCase))); + string.Equals(a.ListId, dataListUrl, StringComparison.OrdinalIgnoreCase))); if (requestType is null) return []; var rows = new List(); @@ -318,12 +339,12 @@ public sealed class RequestManageService( if (matched.Count == 0) return []; var dataById = await ReadDataRowsAsync( - siteUrl, dataList.ServerRelativeUrl, matched.Select(r => r.TicketId).Distinct().ToList(), + siteUrl, dataListUrl, matched.Select(r => r.TicketId).Distinct().ToList(), cancellationToken); return matched .Select(r => ToUserRow( - r, requestType, siteUrl, dataList.ServerRelativeUrl, approvalList.Title, + r, requestType, siteUrl, dataListUrl, approvalTitle, dataById.GetValueOrDefault(r.TicketId))) .ToList(); }