Files
ss-tools/specs/034-task-status-center/ux_reference.md
busya 3133e50645 perf: fix translate deadlock, speed, trace_id, UI bugs — fullstack patch
## 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
2026-06-18 23:54:57 +03:00

103 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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