Запретить возврат null, унифицировать исключения и вынести тексты в ресурсы #20

Merged
rust merged 4 commits from t16_null_exceptions_resources into main 2026-09-13 14:54:26 +03:00
Owner

Ссылка на задачу: #16

Что сделано

  • Введены доменные исключения Deal.SharedKernel.Errors: DealException (код ошибки + текст из ресурсов), NotFoundException, ValidationException, ConflictException, ServiceUnavailableException.
  • Тексты ошибок вынесены в ресурсы Deal.SharedKernel/Resources/ErrorMessages.resx (нейтральная культура = ru); доступ через ErrorResources/ErrorResourceKeys. Добавление языка — отдельный .resx-спутник без правок кода.
  • HTTP-граница: DealExceptionHandler (IExceptionHandler) — доменный код → 404/400/409/503, непредвиденное → 500 с обобщённым русским текстом; лог с контекстом (метод, путь, tenantId, traceId), стектрейс только в лог.
  • gRPC-граница: RpcCallLoggingInterceptor маппит DealException.ErrorCode → статус gRPC (NotFound/InvalidArgument/FailedPrecondition/Unavailable), прочие сбои → Unknown с текстом из ресурсов.
  • Конверсия «не найдено»: ContainersService, CardsService (карточка/файлы), DiscoveryTasksService бросают NotFoundException; эндпоинты убрали null-проверки.
  • Правила закреплены в docs/spec/Код-стайл-Дейл.md §10.
  • Тесты: ресурсы, HTTP-обработчик, обновлены затронутые тесты сервисов.

Проверки

  • Сборка 5 решений: 0 предупреждений / 0 ошибок.
  • Тесты: core 1348, telegram 130, ai 52, ml 38, storage 9 — зелёные.

Согласованные исключения (null допустим)

  • Выборки-запросы репозиториев/сторов (Get* возвращает null — «нет строки»).
  • Парсеры/извлечение полей (JsonExtractor, AmountParser, ContactsQualifier, LocalFieldsParser, BudgetNormalizer и т.п.) — «нет значения».
  • Ожидаемые ветки аутентификации (ResolveSessionAsync, LogoutAsync без impersonation).

Вынесено в отдельную задачу

  • CardResultDto-потоки (AddLink/RemoveLink/MoveStage и др.), MlReviewService, pipeline-воркеры, DiscoveryCandidatesService — требуют решения Result-паттерн vs исключения.
Ссылка на задачу: https://gitea.khomegeneric.keenetic.pro/rust/Deal/issues/16 ## Что сделано - Введены доменные исключения `Deal.SharedKernel.Errors`: `DealException` (код ошибки + текст из ресурсов), `NotFoundException`, `ValidationException`, `ConflictException`, `ServiceUnavailableException`. - Тексты ошибок вынесены в ресурсы `Deal.SharedKernel/Resources/ErrorMessages.resx` (нейтральная культура = ru); доступ через `ErrorResources`/`ErrorResourceKeys`. Добавление языка — отдельный `.resx`-спутник без правок кода. - HTTP-граница: `DealExceptionHandler` (`IExceptionHandler`) — доменный код → 404/400/409/503, непредвиденное → 500 с обобщённым русским текстом; лог с контекстом (метод, путь, tenantId, traceId), стектрейс только в лог. - gRPC-граница: `RpcCallLoggingInterceptor` маппит `DealException.ErrorCode` → статус gRPC (NotFound/InvalidArgument/FailedPrecondition/Unavailable), прочие сбои → Unknown с текстом из ресурсов. - Конверсия «не найдено»: `ContainersService`, `CardsService` (карточка/файлы), `DiscoveryTasksService` бросают `NotFoundException`; эндпоинты убрали null-проверки. - Правила закреплены в `docs/spec/Код-стайл-Дейл.md` §10. - Тесты: ресурсы, HTTP-обработчик, обновлены затронутые тесты сервисов. ## Проверки - Сборка 5 решений: 0 предупреждений / 0 ошибок. - Тесты: core 1348, telegram 130, ai 52, ml 38, storage 9 — зелёные. ## Согласованные исключения (null допустим) - Выборки-запросы репозиториев/сторов (`Get*` возвращает null — «нет строки»). - Парсеры/извлечение полей (JsonExtractor, AmountParser, ContactsQualifier, LocalFieldsParser, BudgetNormalizer и т.п.) — «нет значения». - Ожидаемые ветки аутентификации (`ResolveSessionAsync`, `LogoutAsync` без impersonation). ## Вынесено в отдельную задачу - `CardResultDto`-потоки (`AddLink`/`RemoveLink`/`MoveStage` и др.), `MlReviewService`, pipeline-воркеры, `DiscoveryCandidatesService` — требуют решения Result-паттерн vs исключения.
stepan added 3 commits 2026-09-13 14:33:12 +03:00
DealException/NotFoundException/Validation/Conflict/ServiceUnavailable с кодом ошибки, тексты в ErrorMessages.resx. Общий HTTP-обработчик (DealExceptionHandler) и маппинг в gRPC-интерцепторе: доменные ошибки → статус, прочие → обобщённый текст без стектрейса. Правила закреплены в код-стайле §10.
CardsService (карточка/файл) и ContainersService бросают NotFoundException вместо возврата null; эндпоинты больше не проверяют null — 404 отдаёт общий обработчик. Тесты обновлены под новое поведение.
Перевести задачи Discovery на NotFoundException
ci / build-test (pull_request) Successful in 2m52s
8661faea70
DiscoveryTasksService (get/patch/delete/start/pause) бросает NotFoundException вместо null; эндпоинты отдают 404 через общий обработчик.
stepan requested review from rust 2026-09-13 14:33:34 +03:00
rust added 1 commit 2026-09-13 14:51:20 +03:00
Merge branch 'main' into t16_null_exceptions_resources
ci / build-test (pull_request) Successful in 3m1s
4526532b1a
rust merged commit beaf20df42 into main 2026-09-13 14:54:26 +03:00
rust deleted branch t16_null_exceptions_resources 2026-09-13 14:54:26 +03:00
Sign in to join this conversation.