Implement asynchronous bumper rendering and add integration tests: refactor BumperAsset to support async rendering, introduce BumperRenderBackgroundService for processing, and create TeleWave.Integration.Tests with Testcontainers-Postgres for comprehensive testing of scheduling and bumper generation scenarios. Update documentation and ensure tests skip if Docker is not available.
This commit is contained in:
@@ -42,7 +42,7 @@
|
||||
### Планировщик / медиа
|
||||
- [x] **M8. Нет таймаута на ffmpeg/ffprobe** — `ProcessRunner.cs` + `MediaOptions` (ffprobe 120с, транскод/рендер 1800с, конфигурируемо).
|
||||
- [x] **M9. Гонка при конкурентной генерации расписания канала** — `ScheduleGenerator.cs` (транзакция + `pg_advisory_xact_lock` по каналу).
|
||||
- [~] **M10. Рендер заставок синхронно внутри тика планировщика** — `ScheduleBumperResolver.cs:174`. _(частично: M8 ограничивает худший случай, кэш делает рендеры редкими, M9 сериализует канал. Полный вынос рендера из тика — отдельная архитектурная задача, флажок ниже.)_
|
||||
- [x] **M10. Рендер заставок синхронно внутри тика планировщика** — вынесен в асинхронную очередь: планировщик создаёт ассет заставки в Pending + кэш-строку и ставит в очередь, ffmpeg крутит новый `BumperRenderBackgroundService` вне тика/транзакции. До готовности плейлист отдаёт филлер.
|
||||
- [x] **M11. Override через полночь не работает** — `SchedulePlannerModels.cs:40` (`EndMinute <= StartMinute` → пустое окно).
|
||||
|
||||
### Фронтенд
|
||||
@@ -66,7 +66,7 @@
|
||||
- [x] **L9. `AllowedHosts: "*"` и dev-креды БД в appsettings.json** — осознанные dev-дефолты, переопределяются env в проде; C2 теперь форсит реальный JWT-ключ. Оставлено как задокументированное.
|
||||
- [x] **L10. SSRF-поверхность в ImageDownloader** (без allowlist схемы/хоста) — `ImageDownloader.cs:16` (allowlist http/https).
|
||||
- [x] **L11. Документация (CLAUDE.md/README) отстала** — обновлены разделы «текущее состояние» и рабочий принцип под реальный объём.
|
||||
- [~] **L12. Пробелы в тестах** — частично: добавлены тесты на M11 (override через полночь), L3 (Single). Полное покрытие фоновых сервисов/оркестрации/эндпоинтов — отдельная задача.
|
||||
- [x] **L12. Пробелы в тестах** — добавлен проект `TeleWave.Integration.Tests` на Testcontainers-Postgres: генерация расписания, M10 (Pending-заставки + очередь), M9 (advisory-lock против гонки), M7 (откат Register), M5 (транзакция DeleteShowMedia). При отсутствии Docker тесты пропускаются (SkippableFact). Плюс unit-тесты на M11/L3.
|
||||
|
||||
---
|
||||
|
||||
@@ -166,13 +166,43 @@ Api:EnableOpenApi неявно). Тесты: +2 domain (override через по
|
||||
|
||||
---
|
||||
|
||||
## Осталось (флажки на будущее — требуют отдельного решения)
|
||||
## Журнал — M10 (async-рендер заставок) и L12 (интеграционные тесты)
|
||||
|
||||
- **M10 (полностью)** — вынести рендер ТВ-заставок из тика планировщика: генерировать расписание с
|
||||
плейсхолдерами и рендерить ассеты асинхронно, чтобы один канал не задерживал достройку остальных и
|
||||
чтобы не держать транзакцию/advisory-lock во время ffmpeg.
|
||||
- **L12 (полностью)** — интеграционные тесты фоновых сервисов (media-конвейер, планировщик),
|
||||
оркестрации `ScheduleGenerator`, эндпоинтов (нужен реальный/контейнерный Postgres — InMemory не
|
||||
тянет транзакции/advisory-lock/raw SQL).
|
||||
- **M15 (доменно)** — если нужны разные файлы с одинаковым именем: пересмотреть уникальность
|
||||
`MediaAsset` (сейчас по `OriginalFileName`).
|
||||
### 2026-07-25 — M10: асинхронная очередь рендера заставок
|
||||
|
||||
- **Домен**: `BumperAsset` получил `ChannelId`/`TemplateId`/`VariantId` (чтобы фоновый рендерер
|
||||
восстановил спецификацию), фабрика обновлена; миграция `BumperAssetRenderContext` (Guid-колонки с
|
||||
дефолтом для существующих строк — самовосстановление при перерендере). `MediaAsset.RegisterGenerated`
|
||||
теперь честно Pending до готовности.
|
||||
- **Очередь**: `IBumperRenderQueue` + `BumperRenderQueue` (сигнал поверх Channel, как у медиа).
|
||||
- **`ScheduleBumperResolver`**: больше не рендерит — создаёт Pending-ассет (Source=Generated) + кэш-строку
|
||||
и ставит в очередь; переиспользует Ready/Pending/Processing, перерендерит только Failed (по новейшей
|
||||
кэш-строке). Тик планировщика и его транзакция больше не держатся во время ffmpeg (снимает и остаток M9).
|
||||
- **`BumperRenderBackgroundService`**: последовательно берёт Pending Generated → восстанавливает спеку
|
||||
(`BumperSpecFactory`) → ffmpeg → MarkReady/MarkFailed; сброс прерванных на старте; idle-poll 30с.
|
||||
- **`MediaProcessingBackgroundService`**: Generated-ассеты исключены из claim/reset (их обслуживает
|
||||
рендерер заставок).
|
||||
- **Стриминг менять не пришлось**: `GetLivePlaylistQueryHandler` уже фильтрует по `Status==Ready` →
|
||||
Pending-заставка автоматически деградирует в филлер, пока рендерится.
|
||||
- **Поведение**: заставка перехода впервые появляется на тик позже (до этого — филлер); дальше берётся
|
||||
из кэша. Осознанный компромисс (выбран владельцем).
|
||||
|
||||
### 2026-07-25 — L12: интеграционные тесты на Testcontainers-Postgres
|
||||
|
||||
Новый проект `tests/TeleWave.Integration.Tests` (в `.slnx`): поднимает `postgres:16-alpine`, применяет
|
||||
реальные миграции, гоняет то, что InMemory не умеет (транзакции, advisory-lock, ExecuteDelete). 5 тестов:
|
||||
генерация Program-расписания; создание Pending-заставок (Generated) + постановка в очередь (M10);
|
||||
сериализация конкурентной генерации advisory-lock'ом без перекрытий (M9); откат Register при сбое
|
||||
переноса файла (M7); атомарное удаление в DeleteShowMedia (M5). При отсутствии Docker — `SkippableFact`
|
||||
пропускает (CI на раннере без Docker не падает; `dotnet test TeleWave.slnx` в CI прогонит их при наличии
|
||||
Docker на ubuntu-latest).
|
||||
|
||||
Проверка: сборка решения 0/0; **98 domain + 49 application + 5 integration** зелёные; фронт `tsc`/`oxlint`
|
||||
чистые.
|
||||
|
||||
---
|
||||
|
||||
## Осталось (доменное решение владельца, не дефект)
|
||||
|
||||
- **M15 (доменно)** — если понадобятся разные файлы с одинаковым именем: пересмотреть уникальность
|
||||
`MediaAsset` (сейчас по `OriginalFileName` — намеренно, клиент это зеркалит).
|
||||
|
||||
Reference in New Issue
Block a user