Кешировать пару «список согласования — список данных» в by-approver

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
gorbenko.pavel
2026-10-02 15:51:27 +05:00
parent 90b58ee091
commit 99ce7ed9b2
@@ -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<string, (string ApprovalTitle, string DataListUrl)> 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<ManagedApprovalRowDto>();
@@ -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();
}