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
This commit is contained in:
@@ -66,7 +66,6 @@ async def submit_correction(
|
||||
# @POST All corrections applied or none with conflict list.
|
||||
# @SIDE_EFFECT Creates/updates DictionaryEntry rows; commits once.
|
||||
# @RELATION DEPENDS_ON -> [DictionaryManager]
|
||||
# @COMPLEXITY 4
|
||||
|
||||
@router.post("/corrections/bulk")
|
||||
async def submit_bulk_corrections(
|
||||
|
||||
@@ -204,7 +204,6 @@ async def duplicate_job(
|
||||
# @SIDE_EFFECT Queries Superset API for dataset detail and database info.
|
||||
# @RATIONALE Dialect detection from Superset connection cached on TranslationJob at save time.
|
||||
# @REJECTED Hardcoding dialect list per database — would drift from actual Superset config.
|
||||
# @COMPLEXITY 4
|
||||
|
||||
@router.get("/datasources")
|
||||
async def list_datasources(
|
||||
|
||||
@@ -47,7 +47,6 @@ async def get_metrics(
|
||||
# @BRIEF Get aggregated metrics for a specific job.
|
||||
# @PRE User has translate.metrics.view permission.
|
||||
# @POST Returns metrics dict.
|
||||
# @COMPLEXITY 4
|
||||
|
||||
@router.get("/jobs/{job_id}/metrics")
|
||||
async def get_job_metrics(
|
||||
|
||||
@@ -178,7 +178,6 @@ async def get_run_detail(
|
||||
# @BRIEF Download a CSV of skipped translation records from a run.
|
||||
# @PRE User has translate.job.view permission.
|
||||
# @POST Returns CSV file of skipped records.
|
||||
# @COMPLEXITY 4
|
||||
|
||||
@router.get("/runs/{run_id}/skipped.csv")
|
||||
async def download_skipped_csv(
|
||||
|
||||
@@ -216,7 +216,6 @@ async def delete_schedule(
|
||||
# @BRIEF Preview next N executions for a job's schedule.
|
||||
# @PRE User has translate.schedule.view permission.
|
||||
# @POST Returns next execution times.
|
||||
# @COMPLEXITY 4
|
||||
|
||||
@router.get("/jobs/{job_id}/schedule/next-executions")
|
||||
async def get_next_executions(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#region ValidationTasksRoutes [C:4] [TYPE Module] [SEMANTICS fastapi, validation, api, task, run]
|
||||
# #region ValidationTasksRoutes [C:4] [TYPE Module] [SEMANTICS fastapi, validation, api, task, run]
|
||||
# @BRIEF API routes for validation task management — v2 CRUD with run history and Superset URL parsing.
|
||||
# @LAYER API
|
||||
# @RELATION DEPENDS_ON -> [ValidationTaskService]
|
||||
|
||||
Reference in New Issue
Block a user