## Backend (7 production files + 6 test files) ### P0-2: LLM output truncation cascade fix - _token_budget.py: OUTPUT_PER_ROW_PER_LANG 120→200, OUTPUT_SAFETY_FACTOR 0.70→0.55 - Prevents finish_reason=length → split → retry cascade (3 calls → 1 call per batch) - P2-8: added qwen-flash/qwen-plus/qwen-max/qwen-coder to PROVIDER_DEFAULTS ### P1-4/P1-5: EncryptionManager singleton - encryption.py: get_encryption_manager() process-wide singleton - llm_provider.py: use singleton instead of new EncryptionManager() per batch - Eliminates ~90 redundant Fernet key validations per translation run ### P1-6: Cache-hit log aggregation - _batch_proc.py: one log per batch (batch_rows + cache_hits) instead of per-row - 1076 log lines → ~30 per run ### P1-7: Timezone-aware datetime fix - scheduler.py: _ensure_aware() helper for naive DB datetime → UTC-aware - Fixes TypeError in scheduled translation concurrency check ### P2-9: Connection test timeout - connection_service.py: asyncio.wait_for(15s) on all dialect tests - Prevents 2-minute UI hangs from DNS/TCP stalls ### Trace ID propagation - middleware/trace.py: inject x-trace-id response header via ASGI send wrapper ### Test fixes & integration tests - test_scheduler.py: AsyncMock for execute_run, mock get_async_job_runner - test_sql_insert_service.py: AsyncMock for execute_sql - test_token_budget.py: batch_size 50→45 for new OUTPUT_PER_ROW_PER_LANG=200 - test_encryption.py: +2 singleton tests - test_scheduler_ensure_aware.py: +4 (naive→aware, passthrough, None, subtraction) - test_batch_classify_persist.py: +2 cache-hit aggregation tests - test_connection_service_edge.py: +2 timeout tests - test_trace_middleware.py: +4 x-trace-id header tests - test_token_budget.py: +4 qwen-flash/O200 tests ## Frontend (7 production files + 5 test files) ### Trace ID propagation - api.ts: _captureTraceId() reads x-trace-id → setTraceId() in fetchApi/requestApi/postApi/deleteApi ### Duplicate datasource columns fetch - ConfigTabForm.svelte: guard availableColumns.length === 0 before fetch ### Admin pages Svelte 5 runes fix - admin/users/+page.svelte: plain let → () for all template-bound vars - admin/roles/+page.svelte: same fix - Both pages were stuck on «Загрузка...» due to mixed reactivity models ### Validation popover positioning - +page.svelte: pass trigger HTMLElement instead of event - DashboardHubModel.svelte.ts: toggleValidationPopover(HTMLElement), closeValidationPopover() - Added X close button + click-outside overlay + i18n ### Test fixes & integration tests - api.test.ts: mock setTraceId/getTraceId, +3 _captureTraceId tests - provider_config.integration.test.ts: handleDelete→promptDeleteProvider - DatasetPreview.test.ts: dashboards/ → ROUTES.dashboards - test_config_tab_form.svelte.js: +2 columns fetch guard tests (NEW) - admin-users.test.ts: +3 loading→table tests (NEW) - admin-roles.test.ts: +2 loading→table tests (NEW) ## Semantic curation - Removed @COMPLEXITY N from 6 route files + metrics.py (duplicate of [C:N]) - Added [C:N] to 2 orphan child contracts in metrics.py - Added [C:N] + @BRIEF to 4 frontend anchors - Fixed #region → # #region consistency in validation_tasks.py ## Verification - Backend: 608 pytest passed (0 failures) - Frontend: 2472 vitest passed (128 files, 0 failures) - Frontend build: ✓ built in 18s - Browser: dashboards, admin/users, admin/roles, validation popover — all green
103 lines
14 KiB
Markdown
103 lines
14 KiB
Markdown
#region UxReference [C:3] [TYPE ADR] [SEMANTICS ux, reference, task, status, monitoring]
|
||
@BRIEF UX interaction reference — операторский центр просмотра статусов всех фоновых задач superset-tools. Описывает персону, потоки взаимодействия, состояния интерфейса и сценарии восстановления.
|
||
|
||
**Feature Branch**: `034-task-status-center`
|
||
**Created**: 2026-06-18 | **Status**: Draft
|
||
|
||
## 1. User Persona & Context
|
||
|
||
* **Who is the user?**: DevOps-инженер или администратор superset-tools, отвечающий за мониторинг фоновых операций: переводы контента БД, миграции дашбордов между средами, резервное копирование, LLM-валидацию дашбордов.
|
||
* **What is their goal?**: В одном месте быстро оценить состояние всех фоновых задач системы — что выполняется, что ждёт очереди, что упало; найти конкретную задачу и перейти к её логам для диагностики.
|
||
* **Context**: Работа в браузере (десктоп, планшет) в корпоративной сети. Пользователь может находиться на любой странице superset-tools и перейти в раздел «Отчёты» (`/reports`) через навигацию. Страница `/reports` перерабатывается: существующий список отчётов дополняется сводной панелью и real-time обновлениями.
|
||
|
||
## 2. The "Happy Path" Narrative
|
||
|
||
Администратор открывает раздел «Отчёты» (`/reports`) из бокового меню. Страница загружается мгновенно: в верхней части — сводная панель с цветными счётчиками: «Выполняется: 3 перевода, 1 миграция», «Упало: 2 валидации». Ниже — знакомый список отчётов (задач), по умолчанию активные сверху. Администратор замечает, что миграция дашборда «Отчёт по энергопотреблению» выполняется уже 15 минут — кликает по задаче, открывается Task Drawer с живыми логами. Пока администратор изучает логи, в сводке счётчик «Выполняется» уменьшается — бекап только что завершился успешно, и администратор видит это без перезагрузки страницы.
|
||
|
||
## 3. Interface Mockups
|
||
|
||
### UI Layout & Flow
|
||
|
||
**Page**: `/reports` — переработанный раздел «Отчёты» (Task Status Center)
|
||
|
||
* **Layout**: Одноколоночный, максимальная ширина 7xl, с отступами. Три зоны по вертикали:
|
||
1. **PageHeader** — заголовок «Центр статусов» с кнопкой ручного обновления (на случай проблем с WebSocket).
|
||
2. **Summary Panel** — горизонтальная панель сводки: сетка из карточек (2-3 строки × 4-6 колонок), каждая карточка = тип задачи × статус, показывает количество задач. Цвета: running — синий/primary, pending — серый/muted, success — зелёный/success, failed — красный/destructive, awaiting_input — жёлтый/warning.
|
||
3. **Task List** — основная область: фильтры (горизонтальная панель) + таблица/список задач с пагинацией.
|
||
|
||
* **Key Elements**:
|
||
* **Summary Card**: Кликабельная карточка сводки. При клике — фильтрует список задач по типу и статусу карточки. Пример: клик по карточке «Миграция / Выполняется (3)» → список показывает только выполняющиеся миграции.
|
||
* **Filter Bar**: Горизонтальная панель фильтров над списком. Содержит: выпадающий список типов задач (multi-select), выпадающий список статусов (multi-select), текстовое поле поиска, селект временного диапазона (последний час / сегодня / неделя / всё время).
|
||
* **Task Row**: Строка задачи в списке. Содержит: иконку типа, название/идентификатор задачи, статус-бейдж, время запуска (относительное: «2 мин назад»), длительность, название связанного ресурса (дашборда/конфигурации). При наведении — тултип с подробностями. При клике — открывает Task Drawer.
|
||
* **Connection Indicator**: Маленький индикатор в углу экрана (зелёный = connected, жёлтый = reconnecting, красный = disconnected). При клике показывает статус соединения и время последнего обновления.
|
||
|
||
* **Contract Mapping**:
|
||
* **`@UX_STATE`**:
|
||
* **idle** — страница загружена, данные актуальны, WebSocket подключён.
|
||
* **loading** — первоначальная загрузка: скелетон-заглушки (pulse-анимация) вместо сводки и списка.
|
||
* **empty** — нет ни одной задачи в системе: пустое состояние с иконкой и пояснительным текстом.
|
||
* **disconnected** — WebSocket разорван: индикатор красный, баннер «Соединение потеряно. Переподключение...», данные последнего известного состояния заморожены.
|
||
* **reconnecting** — WebSocket переподключается: индикатор жёлтый с анимацией.
|
||
* **error** — ошибка загрузки данных: баннер с сообщением об ошибке и кнопкой «Повторить».
|
||
* **`@UX_FEEDBACK`**:
|
||
* Изменение статуса задачи в списке — анимированное обновление (плавное изменение цвета бейджа).
|
||
* Новая задача появляется в списке — анимированное появление (slide-in сверху).
|
||
* Завершение задачи — кратковременное выделение строки (зелёное/красное) и обновление счётчика в сводке.
|
||
* Ошибка фильтрации — инлайн-сообщение «Нет задач, соответствующих фильтрам» с кнопкой «Сбросить фильтры».
|
||
* **`@UX_RECOVERY`**:
|
||
* Разрыв WebSocket → автоматический reconnect с экспоненциальной задержкой (1с, 2с, 4с, 8с, макс 30с). Кнопка «Подключиться сейчас» для ручного reconnect.
|
||
* Ошибка загрузки → кнопка «Повторить загрузку».
|
||
* Пустой результат поиска → кнопка «Сбросить фильтры».
|
||
* **`@UX_REACTIVITY`**: Сводка и список — производные от модели (`TaskCenterModel` в `.svelte.ts`). Модель подписывается на WebSocket `/ws/task-events` через `$effect`. Данные сводки — `$derived` от полного списка задач в модели. Фильтры — `$state` атомы модели, изменение любого фильтра пересчитывает отфильтрованный список через `$derived`.
|
||
* **Screen Model**: `TaskCenterModel` (`frontend/src/lib/models/TaskCenterModel.svelte.ts`) — [TYPE Model], объявляет `@STATE` (screenState, tasks, summary, filters), `@ACTION` (applyFilter, clearFilters, selectTask, refresh), `@INVARIANT` (активные задачи всегда сверху, счётчики сводки = агрегация tasks).
|
||
* **States**:
|
||
* **Idle/Default**: Сводка и список загружены, индикатор соединения зелёный, фильтры пустые (показываются все задачи, активные сверху).
|
||
* **Loading**: Вся страница — skeleton placeholder: 4 карточки-скелетона в сводке, 10 строк-скелетонов в списке.
|
||
* **Empty**: Иконка (inbox) + текст «Нет активных задач» + ссылки «Запустить перевод», «Запустить миграцию», «Запустить бекап».
|
||
* **Disconnected**: Данные последнего известного состояния остаются видимыми, индикатор красный, баннер сверху: «Соединение потеряно. Попытка переподключения... [Подключиться сейчас]».
|
||
* **Error**: Баннер с ошибкой + кнопка «Повторить». Сводка и список скрыты или показывают последние кешированные данные с пометкой «Данные могут быть неактуальны».
|
||
|
||
## 4. The "Error" Experience
|
||
|
||
**Philosophy**: Не просто сообщать об ошибке — направлять оператора к решению. Каждый сценарий отказа имеет путь восстановления.
|
||
|
||
**Semantic Requirement**: Every documented failure path here should map to `@UX_RECOVERY` and, where relevant, `@UX_FEEDBACK` in the generated component contracts.
|
||
|
||
### Scenario A: WebSocket разрыв соединения
|
||
|
||
* **User Action**: Сетевой сбой, перезапуск backend, или таймаут бездействия.
|
||
* **System Response**:
|
||
* Индикатор соединения меняется на жёлтый (Reconnecting) с анимацией пульсации.
|
||
* Через 2 секунды неудачных попыток — баннер «Соединение потеряно. Попытка переподключения... [Подключиться сейчас]».
|
||
* Данные последнего известного состояния остаются на экране с пометкой «Обновлено: 2 мин назад».
|
||
* **Recovery**: Автоматический reconnect с экспоненциальной задержкой (1с → 2с → 4с → 8с → ... макс 30с). Кнопка «Подключиться сейчас» для немедленной попытки.
|
||
|
||
### Scenario B: Ошибка загрузки начальных данных
|
||
|
||
* **User Action**: Открытие страницы, а backend API недоступен (503).
|
||
* **System Response**:
|
||
* Баннер: «Не удалось загрузить данные задач. Сервер временно недоступен.»
|
||
* Кнопка «Повторить загрузку».
|
||
* **Recovery**: Ручная повторная попытка. Автоматический retry через 10 секунд с уведомлением.
|
||
|
||
### Scenario C: Пустой результат фильтрации
|
||
|
||
* **User Action**: Применил фильтр «Тип: Бекап, Статус: Выполняется», но выполняющихся бекапов нет.
|
||
* **System Response**:
|
||
* Вместо списка — EmptyState с текстом «Нет выполняющихся бекапов».
|
||
* Кнопка «Сбросить фильтры» возвращает к полному списку.
|
||
* **Recovery**: Оператор сбрасывает фильтры одним кликом.
|
||
|
||
### Scenario D: Задача упала — быстрый переход к логам
|
||
|
||
* **User Action**: Оператор видит красный бейдж «FAILED» на задаче.
|
||
* **System Response**: Строка задачи подсвечена красным слева (destructive ring border).
|
||
* **Recovery**: Клик по задаче → открывается Task Drawer, скроллится к последней ошибке в логах. Кнопка «Перезапустить» в Task Drawer (если тип задачи поддерживает перезапуск).
|
||
|
||
## 5. Tone & Voice
|
||
|
||
* **Style**: Деловой, лаконичный, технический. Русский язык.
|
||
* **Terminology**: «Задача» (не job), «Выполняется» (не in progress), «Упала» (не error/failed в UI), «Ожидает» (не pending), «Ожидает ввода» (не awaiting input). Иконки типов: перевод (globe), миграция (arrows-right-left), бекап (archive), валидация (shield-check), документация (file-text).
|
||
|
||
#endregion UxReference
|