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

14 KiB
Raw Blame History

#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