Больше двух параметров — каждый на отдельной строке (закрывающая скобка в конце последнего); два и меньше — в одну строку. Правило добавлено в docs/spec/Код-стайл-Дейл.md; применено к 628 сигнатурам в 253 файлах.
93 lines
5.1 KiB
C#
93 lines
5.1 KiB
C#
using Deal.Modules.Settings.Application.Abstractions;
|
||
using Deal.Modules.Settings.Application.Models;
|
||
using Deal.Modules.Settings.Application.Registrars;
|
||
using Deal.Modules.Settings.Application.Services;
|
||
using Deal.Modules.Discovery.Application.Abstractions;
|
||
using Deal.Modules.Discovery.Application.Exceptions;
|
||
using Deal.Modules.Discovery.Application.Extensions;
|
||
using Deal.Modules.Discovery.Application.Models;
|
||
using Deal.Modules.Discovery.Application.Registrars;
|
||
|
||
namespace Deal.Modules.Discovery.Application.Services;
|
||
|
||
/// <summary>
|
||
/// План-бюджет авто-вступлений Discovery: лимит и правило суммы (python L80–111, Ruling 9).
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Правило 1:1 с discovery.py: суточный лимит discJoinLimit (настройка, дефолт 50 — SettingsDefaults) — верхняя
|
||
/// граница plan_joins одной задачи (<see cref="AssertPlanAsync"/>); сумма plan_joins активных задач (status NOT IN
|
||
/// done/failed) плюс новая/увеличиваемая задача не должна превышать лимит (<see cref="AssertBudgetAsync"/>).
|
||
/// Итог семантики: задача на 50 занимает весь бюджет (другую создать нельзя); задача на 25 оставляет остаток
|
||
/// 25 (следующая может быть не больше 25). Тексты 400 — 1:1 с python (L97–110).
|
||
/// </remarks>
|
||
public sealed class DiscoveryPlanGuard(IDiscoveryStore store, ISettingsStore settings)
|
||
{
|
||
/// <summary>
|
||
/// 400: план меньше 1 (python L97 «plan_joins должен быть не меньше 1»).
|
||
/// </summary>
|
||
public const string PlanTooSmallDetail = "plan_joins должен быть не меньше 1";
|
||
|
||
/// <summary>
|
||
/// 400: план больше суточного лимита (python L100). Формат: {plan}, {limit}.
|
||
/// </summary>
|
||
public const string PlanTooBigFormat = "plan_joins {0} больше суточного лимита авто-вступлений ({1})";
|
||
|
||
/// <summary>
|
||
/// 400: бюджет исчерпан (python L108–110). Формат: {used}, {limit}, {plan}.
|
||
/// </summary>
|
||
public const string BudgetExceededFormat =
|
||
"Бюджет авто-вступлений исчерпан: задачи уже занимают {0} из {1} в сутки, ещё {2} не влезает";
|
||
|
||
/// <summary>
|
||
/// Верхняя граница plan_joins: суточный лимит авто-вступлений (python _plan_limit L80–82).
|
||
/// </summary>
|
||
/// <param name="ct">Токен отмены.</param>
|
||
/// <returns>discJoinLimit настройки (дефолт 50) с нижней границей 1.</returns>
|
||
public async Task<int> PlanLimitAsync(CancellationToken ct)
|
||
{
|
||
int limit = (await TenantSettingsSnapshot.LoadAsync(settings, ct))
|
||
.GetInt(SettingsKeys.DiscJoinLimit, SettingsDefaults.DiscJoinLimit);
|
||
return Math.Max(1, limit);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Проверяет план новой задачи: 1..discJoinLimit (python _assert_plan L94–100).
|
||
/// </summary>
|
||
/// <param name="planJoins">Запрашиваемый план авто-вступлений.</param>
|
||
/// <param name="ct">Токен отмены.</param>
|
||
/// <exception cref="DiscoveryValidationException">План меньше 1 или больше суточного лимита (тексты python).</exception>
|
||
public async Task AssertPlanAsync(int planJoins, CancellationToken ct)
|
||
{
|
||
if (planJoins < 1)
|
||
{
|
||
throw new DiscoveryValidationException(PlanTooSmallDetail);
|
||
}
|
||
|
||
int limit = await PlanLimitAsync(ct).ConfigureAwait(false);
|
||
if (planJoins > limit)
|
||
{
|
||
throw new DiscoveryValidationException(string.Format(PlanTooBigFormat, planJoins, limit));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Проверяет бюджет: занято активными задачами + новая ≤ discJoinLimit (python _assert_budget L103–111).
|
||
/// </summary>
|
||
/// <param name="planJoins">План создаваемой/итоговый план увеличиваемой задачи.</param>
|
||
/// <param name="excludeTaskId">Id задачи, исключаемой из занятого бюджета (patch-рост плана); null — создание.</param>
|
||
/// <param name="ct">Токен отмены.</param>
|
||
/// <exception cref="DiscoveryValidationException">Бюджет исчерпан (текст python L108–110).</exception>
|
||
public async Task AssertBudgetAsync(
|
||
int planJoins,
|
||
string? excludeTaskId,
|
||
CancellationToken ct)
|
||
{
|
||
int limit = await PlanLimitAsync(ct).ConfigureAwait(false);
|
||
int used = await store.SumActivePlanAsync(excludeTaskId, ct).ConfigureAwait(false);
|
||
if (used + planJoins > limit)
|
||
{
|
||
throw new DiscoveryValidationException(string.Format(BudgetExceededFormat, used, limit, planJoins));
|
||
}
|
||
}
|
||
}
|