Разбить модули Deal.Modules.* по назначению
Application проектов Discovery, Kanban, Pipeline, Settings, Tenants разделён на Abstractions/Exceptions/Extensions/Models/Registrars/Services; namespace приведён к путям, using потребителей мигрированы и дедуплицированы (169 файлов), cref/FQN обновлены.
This commit is contained in:
@@ -6,21 +6,21 @@ namespace Deal.Modules.Discovery.Application.Models;
|
||||
/// <remarks>
|
||||
/// Поля 1:1 с _candidate_view discovery.py L140–158 и строкой disc_candidates (db.py L159–176). marks/topics —
|
||||
/// JSON-колонки, наружу всегда списки (marks — строки-метки, topics — элементы <see cref="DiscoveryTopicDto"/> для
|
||||
/// форумов). Статус — <see cref="Deal.Modules.Discovery.Application.DiscoveryCandidateStatuses"/>; переводы в
|
||||
/// форумов). Статус — <see cref="Deal.Modules.Discovery.Application.Models.DiscoveryCandidateStatuses"/>; переводы в
|
||||
/// joined/rejected — только через mark_joined/mark_rejected.
|
||||
/// </remarks>
|
||||
/// <param name="DialogId">Подписанный id источника (первичный ключ кандидата; как Dialogs.Id).</param>
|
||||
/// <param name="TaskId">Id задачи поиска, которой принадлежит кандидат.</param>
|
||||
/// <param name="Name">Отображаемое имя источника (пусто → DialogId).</param>
|
||||
/// <param name="Username">Username (handle) источника; пуст, если нет публичного username.</param>
|
||||
/// <param name="Kind">Тип источника: channel|group|forum (см. <see cref="Deal.Modules.Discovery.Application.DiscoveryCandidateKinds"/>).</param>
|
||||
/// <param name="Kind">Тип источника: channel|group|forum (см. <see cref="Deal.Modules.Discovery.Application.Models.DiscoveryCandidateKinds"/>).</param>
|
||||
/// <param name="Hue">Цвет источника из палитры DIALOG_HUES (hex «#rrggbb»; дефолт «#666»).</param>
|
||||
/// <param name="Participants">Число участников (после discovery_info); null — неизвестно.</param>
|
||||
/// <param name="LangRu">Язык источника: true — русский, false — не русский, null — не определён.</param>
|
||||
/// <param name="Marks">Метки оценки («закрытая группа (история скрыта)», «мало сообщений», …).</param>
|
||||
/// <param name="Topics">Оценка тем форума (kind=forum; для каналов/групп пуст).</param>
|
||||
/// <param name="FitRatio">Доля подходящих сообщений оценки (0..1); null — контент не оценён.</param>
|
||||
/// <param name="Status">Статус кандидата (см. <see cref="Deal.Modules.Discovery.Application.DiscoveryCandidateStatuses"/>).</param>
|
||||
/// <param name="Status">Статус кандидата (см. <see cref="Deal.Modules.Discovery.Application.Models.DiscoveryCandidateStatuses"/>).</param>
|
||||
/// <param name="AutoJoined">Вступили автоматически (воркером); false — вручную (join из UI).</param>
|
||||
/// <param name="JoinFailures">Неудачные авто-вступления подряд (3 → кандидат удаляется, Task 18).</param>
|
||||
/// <param name="CreatedAt">Время добавления, epoch-ms.</param>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Типы источников-кандидатов Discovery (колонка DiscCandidates.Kind; api-map §4.8, discovery_worker _kind_code).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// EN-канон контракта 1:1 с кандидатами Telegram: channel — канал, group — группа, forum — форум (группа с
|
||||
/// темами; оценка идёт по темам, discovery_worker L299–307). Личные чаты/боты поиском не предлагаются.
|
||||
/// </remarks>
|
||||
public static class DiscoveryCandidateKinds
|
||||
{
|
||||
/// <summary>
|
||||
/// Канал.
|
||||
/// </summary>
|
||||
public const string Channel = "channel";
|
||||
|
||||
/// <summary>
|
||||
/// Группа.
|
||||
/// </summary>
|
||||
public const string Group = "group";
|
||||
|
||||
/// <summary>
|
||||
/// Форум (группа с темами; topics заполняются оценкой).
|
||||
/// </summary>
|
||||
public const string Forum = "forum";
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Статусы кандидата Discovery (колонка DiscCandidates.Status; discovery.py L171, api-map §4.8).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Цепочка 1:1 с прототипом: new — найден поиском, ждёт оценки; review — оценён, ждёт решения (воркер/человек);
|
||||
/// joined — вступили (только mark_joined: счётчик задачи + лог join_auto/join_manual); rejected — отклонён
|
||||
/// (только mark_rejected: счётчик задачи + лог + чёрный список). Переводы в joined/rejected минуя mark_* —
|
||||
/// запрещены (discovery.py L16–18). Активные статусы (python _ACTIVE_CANDIDATE L35) запрещают повторное
|
||||
/// добавление источника в задачу.
|
||||
/// </remarks>
|
||||
public static class DiscoveryCandidateStatuses
|
||||
{
|
||||
/// <summary>
|
||||
/// Найден поиском, ещё не оценён.
|
||||
/// </summary>
|
||||
public const string New = "new";
|
||||
|
||||
/// <summary>
|
||||
/// Оценён (метки/фит проставлены), ждёт вступления/решения.
|
||||
/// </summary>
|
||||
public const string Review = "review";
|
||||
|
||||
/// <summary>
|
||||
/// Вступили в источник (терминал: счётчик joined задачи).
|
||||
/// </summary>
|
||||
public const string Joined = "joined";
|
||||
|
||||
/// <summary>
|
||||
/// Отклонён и помещен в чёрный список (терминал: счётчик rejected).
|
||||
/// </summary>
|
||||
public const string Rejected = "rejected";
|
||||
|
||||
/// <summary>
|
||||
/// Статусы, при которых повторное добавление источника запрещено (python _ACTIVE_CANDIDATE L35).
|
||||
/// </summary>
|
||||
/// <param name="status">Статус кандидата.</param>
|
||||
/// <returns>True — new/review/joined (add_candidate пропускает источник с логом skip).</returns>
|
||||
public static bool IsActive(string status)
|
||||
{
|
||||
return status is New or Review or Joined;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Разрешён ли перевод через set_candidate_status (python L503–504: только new/review).
|
||||
/// </summary>
|
||||
/// <param name="status">Запрашиваемый статус.</param>
|
||||
/// <returns>True — new/review (joined/rejected выставляются только через mark_joined/mark_rejected).</returns>
|
||||
public static bool IsTransitionAllowed(string status)
|
||||
{
|
||||
return status is New or Review;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Счётчики прогресса задачи поиска (колонки DiscTasks Found/Evaluated/Joined/Rejected; discovery.py L359–368).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Соответствие колонкам db.py L150–153: found — найдено кандидатов поиском, evaluated — оценено/пропущено,
|
||||
/// joined — вступили (терминал плана: joined ≥ planJoins → done), rejected — отклонено. bump_counter прототипа
|
||||
/// принимает имя колонки строкой; в .NET поле типизировано перечислением (валидация L361–362 — на этапе компиляции).
|
||||
/// </remarks>
|
||||
public enum DiscoveryCounterField
|
||||
{
|
||||
/// <summary>
|
||||
/// Счётчик «found»: найденные источники (add_candidate).
|
||||
/// </summary>
|
||||
Found,
|
||||
|
||||
/// <summary>
|
||||
/// Счётчик «evaluated»: оценённые/пропущенные кандидаты (воркер).
|
||||
/// </summary>
|
||||
Evaluated,
|
||||
|
||||
/// <summary>
|
||||
/// Счётчик «joined»: вступившие источники (mark_joined).
|
||||
/// </summary>
|
||||
Joined,
|
||||
|
||||
/// <summary>
|
||||
/// Счётчик «rejected»: отклонённые источники (mark_rejected).
|
||||
/// </summary>
|
||||
Rejected,
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Агрегат оценки выборки сообщений (python evaluate_sample L197–226: fit_count/total/fit_ratio/per_message).
|
||||
/// </summary>
|
||||
/// <param name="FitCount">Сколько сообщений подошли под задачу.</param>
|
||||
/// <param name="Total">Всего сообщений выборки.</param>
|
||||
/// <param name="FitRatio">Доля подходящих (fit_count / total; 0 при пустой выборке).</param>
|
||||
/// <param name="PerMessage">Вердикты по сообщениям во входном порядке.</param>
|
||||
public sealed record DiscoveryEvalSample(
|
||||
int FitCount,
|
||||
int Total,
|
||||
double FitRatio,
|
||||
IReadOnlyList<DiscoveryMessageFit> PerMessage);
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Security.Cryptography;
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Префиксы коротких id модуля Discovery и их генерация (прототип store.uid в discovery.py).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Префиксы 1:1 с discovery.py L30–32 (<c>_ID_TASK = "dt_"</c>, <c>_ID_LOG = "dl_"</c>) и api-map §1:
|
||||
/// <c>dt_</c> — задача поиска (DiscTasks), <c>dl_</c> — запись лога задачи (DiscLog). Случайная часть —
|
||||
/// 12 hex-символов (6 байт CSPRNG), как общий генератор PrefixId модуля Kanban (uuid4().hex[:12] прототипа);
|
||||
/// модуль Discovery зависит только от ST + Contracts (план Task 17), поэтому генератор вынесен сюда, а не в
|
||||
/// Kanban. Id генерирует модуль и передаёт в хранилище готовыми (порт id не создаёт).
|
||||
/// </remarks>
|
||||
public static class DiscoveryIdPrefixes
|
||||
{
|
||||
// Размер случайной части в байтах: 6 байт → 12 hex-символов (uuid4().hex[:12]).
|
||||
private const int RandomHexBytes = 6;
|
||||
|
||||
/// <summary>
|
||||
/// Префикс id задачи поиска (таблица DiscTasks; discovery.py store.uid("dt_")).
|
||||
/// </summary>
|
||||
public const string Task = "dt_";
|
||||
|
||||
/// <summary>
|
||||
/// Префикс id записи лога задачи (таблица DiscLog; discovery.py store.uid("dl_")).
|
||||
/// </summary>
|
||||
public const string Log = "dl_";
|
||||
|
||||
/// <summary>
|
||||
/// Новый id задачи поиска: <c>dt_</c> + 12 случайных hex-символов.
|
||||
/// </summary>
|
||||
public static string NewTaskId() => New(Task);
|
||||
|
||||
/// <summary>
|
||||
/// Новый id записи лога: <c>dl_</c> + 12 случайных hex-символов.
|
||||
/// </summary>
|
||||
public static string NewLogId() => New(Log);
|
||||
|
||||
// Новый id: префикс + 12 случайных hex-символов в нижнем регистре.
|
||||
// prefix: Префикс типа записи (см. Task/Log).
|
||||
// Возвращает: Короткий id записи (например, dt_1a2b3c4d5e6f).
|
||||
private static string New(string prefix)
|
||||
{
|
||||
return prefix + Convert.ToHexString(RandomNumberGenerator.GetBytes(RandomHexBytes)).ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@ namespace Deal.Modules.Discovery.Application.Models;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Поля 1:1 с _log_view discovery.py L170–177 и строкой disc_log (db.py L189–195). Событие — каталог
|
||||
/// <see cref="Deal.Modules.Discovery.Application.DiscoveryLogEvents"/> (search|skip|review|join_auto|join_manual|
|
||||
/// <see cref="Deal.Modules.Discovery.Application.Models.DiscoveryLogEvents"/> (search|skip|review|join_auto|join_manual|
|
||||
/// reject|flood|error|done|…). Список — последние события задачи, новые сверху (ORDER BY created_at DESC).
|
||||
/// </remarks>
|
||||
/// <param name="Id">Короткий id записи (префикс <c>dl_</c>).</param>
|
||||
/// <param name="TaskId">Id задачи поиска.</param>
|
||||
/// <param name="Event">Событие (см. <see cref="Deal.Modules.Discovery.Application.DiscoveryLogEvents"/>).</param>
|
||||
/// <param name="Event">Событие (см. <see cref="Deal.Modules.Discovery.Application.Models.DiscoveryLogEvents"/>).</param>
|
||||
/// <param name="Text">Текст/детали события (русская строка 1:1 с прототипом).</param>
|
||||
/// <param name="CreatedAt">Время события, epoch-ms.</param>
|
||||
public sealed record DiscoveryLogDto(
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// События лога задачи Discovery (колонка DiscLog.Event; discovery.py L187–188, api-map §3.8).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Каталог 1:1 с комментарием db.py L187–188: search (завершён проход по ключам), skip (источник пропущен),
|
||||
/// review (кандидат переведён в review), join_auto (авто-вступление воркером), join_manual (ручное вступление),
|
||||
/// leave, reject (отклонён), flood (флуд-стоп), error (сбой шага), done (план задачи выполнен).
|
||||
/// </remarks>
|
||||
public static class DiscoveryLogEvents
|
||||
{
|
||||
/// <summary>
|
||||
/// Поиск: проход по ключам завершён.
|
||||
/// </summary>
|
||||
public const string Search = "search";
|
||||
|
||||
/// <summary>
|
||||
/// Источник пропущен (мониторится/в чёрном списке/уже кандидат/мало участников/…).
|
||||
/// </summary>
|
||||
public const string Skip = "skip";
|
||||
|
||||
/// <summary>
|
||||
/// Кандидат переведён в review (set_candidate_status).
|
||||
/// </summary>
|
||||
public const string Review = "review";
|
||||
|
||||
/// <summary>
|
||||
/// Авто-вступление воркера (mark_joined(auto:true), счётчик суточной квоты).
|
||||
/// </summary>
|
||||
public const string JoinAuto = "join_auto";
|
||||
|
||||
/// <summary>
|
||||
/// Ручное вступление (mark_joined(auto:false), вне квот).
|
||||
/// </summary>
|
||||
public const string JoinManual = "join_manual";
|
||||
|
||||
/// <summary>
|
||||
/// Выход из источника (зарезервировано прототипом).
|
||||
/// </summary>
|
||||
public const string Leave = "leave";
|
||||
|
||||
/// <summary>
|
||||
/// Кандидат отклонён (mark_rejected → чёрный список).
|
||||
/// </summary>
|
||||
public const string Reject = "reject";
|
||||
|
||||
/// <summary>
|
||||
/// FloodWait: авто-вступления остановлены до конца суток.
|
||||
/// </summary>
|
||||
public const string Flood = "flood";
|
||||
|
||||
/// <summary>
|
||||
/// Сбой шага воркера/поиска (не роняет задачу).
|
||||
/// </summary>
|
||||
public const string Error = "error";
|
||||
|
||||
/// <summary>
|
||||
/// План авто-вступлений задачи выполнен (воркер).
|
||||
/// </summary>
|
||||
public const string Done = "done";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Вердикт фита одного сообщения (python evaluate_message L174–194).
|
||||
/// </summary>
|
||||
/// <param name="Fit">True — сообщение относится к сфере/задаче.</param>
|
||||
/// <param name="Reason">Краткая причина вердикта.</param>
|
||||
/// <param name="Source">Источник решения: heuristic|ml|ai.</param>
|
||||
public sealed record DiscoveryMessageFit(bool Fit, string Reason, string Source);
|
||||
@@ -5,7 +5,7 @@ namespace Deal.Modules.Discovery.Application.Models;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Поля 1:1 с _task_view discovery.py L116–137 и строкой disc_tasks (db.py L136–156). JSON-поле keywords
|
||||
/// наружу всегда список строк; статус — <see cref="Deal.Modules.Discovery.Application.DiscoveryTaskStatuses"/>.
|
||||
/// наружу всегда список строк; статус — <see cref="Deal.Modules.Discovery.Application.Models.DiscoveryTaskStatuses"/>.
|
||||
/// createdAt/updatedAt — epoch-ms (времена хранятся UTC, на границе переводятся в ms — конвенция проекта).
|
||||
/// </remarks>
|
||||
/// <param name="Id">Короткий id задачи (префикс <c>dt_</c>).</param>
|
||||
@@ -18,7 +18,7 @@ namespace Deal.Modules.Discovery.Application.Models;
|
||||
/// <param name="SampleSize">Размер выборки сообщений при оценке (≥1; дефолт discEvalSample).</param>
|
||||
/// <param name="PlanJoins">План авто-вступлений задачи (1..discJoinLimit; занимает суточный бюджет).</param>
|
||||
/// <param name="AutoJoin">Авто-вступления воркером включены (иначе кандидатов вступает человек).</param>
|
||||
/// <param name="Status">Статус задачи (см. <see cref="Deal.Modules.Discovery.Application.DiscoveryTaskStatuses"/>).</param>
|
||||
/// <param name="Status">Статус задачи (см. <see cref="Deal.Modules.Discovery.Application.Models.DiscoveryTaskStatuses"/>).</param>
|
||||
/// <param name="SearchIdx">Индекс текущего ключа поиска (прогресс прохода по keywords).</param>
|
||||
/// <param name="SearchDone">Проход по всем ключам завершён (searchIdx ≥ keywords.Count).</param>
|
||||
/// <param name="Found">Найдено кандидатов (счётчик found).</param>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Deal.Modules.Discovery.Application.Models;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Write-модель: содержит полное состояние новой задачи, включая готовый id (<c>dt_...</c>, генерирует модуль —
|
||||
/// <see cref="Deal.Modules.Discovery.Application.DiscoveryIdPrefixes"/>). Служебные значения, вычисленные до
|
||||
/// <see cref="Deal.Modules.Discovery.Application.Models.DiscoveryIdPrefixes"/>). Служебные значения, вычисленные до
|
||||
/// записи: Status=<c>draft</c>, SearchIdx=0, SearchDone=false, счётчики Found/Evaluated/Joined/Rejected=0 —
|
||||
/// как в INSERT прототипа discovery.py L260–280. CreatedAt/UpdatedAt проставляет хранилище (UTC-now);
|
||||
/// keywords адаптер сериализует в JSON при записи.
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Статусы задачи поиска Discovery (колонка DiscTasks.Status; discovery.py L147, api-map §4.8).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// draft — создана, поиск не запускался; running — поиск/оценка/вступления идут; paused — поставлена на паузу
|
||||
/// вручную; done — план авто-вступлений выполнен (воркер, discovery_worker _finish_done); failed — упала/остановлена
|
||||
/// (зарезервировано прототипом). done/failed — терминальные: не занимают бюджет plan_joins (python _DONE_TASK L37)
|
||||
/// и при повторном start сбрасывают прогресс поиска (start_task L332–339).
|
||||
/// </remarks>
|
||||
public static class DiscoveryTaskStatuses
|
||||
{
|
||||
/// <summary>
|
||||
/// Создана, поиск ещё не запускался (значение по умолчанию при INSERT).
|
||||
/// </summary>
|
||||
public const string Draft = "draft";
|
||||
|
||||
/// <summary>
|
||||
/// Поиск запущен (обрабатывается воркером).
|
||||
/// </summary>
|
||||
public const string Running = "running";
|
||||
|
||||
/// <summary>
|
||||
/// Поставлена на паузу вручную (POST …/pause); прогресс поиска сохраняется.
|
||||
/// </summary>
|
||||
public const string Paused = "paused";
|
||||
|
||||
/// <summary>
|
||||
/// План авто-вступлений выполнен (терминальный; повторный start сбрасывает прогресс).
|
||||
/// </summary>
|
||||
public const string Done = "done";
|
||||
|
||||
/// <summary>
|
||||
/// Упала/остановлена (терминальный статус прототипа; повторный start сбрасывает прогресс).
|
||||
/// </summary>
|
||||
public const string Failed = "failed";
|
||||
|
||||
/// <summary>
|
||||
/// Проверка терминального статуса: задача не занимает бюджет plan_joins (python _DONE_TASK L37).
|
||||
/// </summary>
|
||||
/// <param name="status">Статус задачи.</param>
|
||||
/// <returns>True — done/failed (повторный start сбрасывает прогресс поиска, L332–339).</returns>
|
||||
public static bool IsFinished(string status)
|
||||
{
|
||||
return status is Done or Failed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Deal.Contracts.Integrations.Models;
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Группа сообщений форума по теме (python group_by_topic L96–117).
|
||||
/// </summary>
|
||||
/// <param name="TopicKey">Ключ темы: id темы строкой либо «main» (topic_id=null).</param>
|
||||
/// <param name="Title">Сниппет первого непустого текста темы (≤60 символов; пуст — тема без текста).</param>
|
||||
/// <param name="Messages">Сообщения группы во входном порядке.</param>
|
||||
public sealed record DiscoveryTopicGroup(
|
||||
string TopicKey,
|
||||
string Title,
|
||||
IReadOnlyList<TelegramEvalMessageDto> Messages);
|
||||
@@ -0,0 +1,20 @@
|
||||
using Deal.Modules.Discovery.Application.Abstractions;
|
||||
using Deal.Modules.Discovery.Application.Exceptions;
|
||||
using Deal.Modules.Discovery.Application.Extensions;
|
||||
using Deal.Modules.Discovery.Application.Registrars;
|
||||
using Deal.Modules.Discovery.Application.Services;
|
||||
|
||||
namespace Deal.Modules.Discovery.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Результат одного тика discovery-воркера (python discovery_worker L5–6: {action, taskId}).
|
||||
/// </summary>
|
||||
/// <param name="Action">Действие тика (константы <see cref="DiscoveryWorkerService.ActionNone"/>…).</param>
|
||||
/// <param name="TaskId">Id задачи шага (null — действия с задачей не связано).</param>
|
||||
public sealed record DiscoveryWorkerOutcome(string Action, string? TaskId)
|
||||
{
|
||||
/// <summary>
|
||||
/// Результат «работы нет» (none).
|
||||
/// </summary>
|
||||
public static DiscoveryWorkerOutcome None { get; } = new(DiscoveryWorkerService.ActionNone, null);
|
||||
}
|
||||
Reference in New Issue
Block a user