perf: Fix all 7 code analysis issues
HIGH (Performance):
- Replace 8 sync file operations with aiofiles in async context (storage, mail,
report_generator, dms_bridge, ai_assistant)
- Frontend bundle splitting: manualChunks for react-vendor, ui-components, tanstack,
markdown, icons, utils, i18n (ui chunk 936K → ~19K)
MEDIUM (Architecture):
- Worker circular deps: Replace direct plugin imports with job_registry.py pattern
(register_job/get_all_jobs, importlib-based lazy loading)
- App-wide ErrorBoundary: New ErrorBoundary.tsx component, wrapped in AppShell
and all standalone routes
LOW (Code Quality):
- N+1 query fix: selectinload(Contact.contact_persons) in list_contacts()
- O(n²) dedup fix: SQL GROUP BY for email/phone duplicates, Dict-based name grouping
- Response format standardization: 7 routes converted from plain arrays to
{items: [...], total: N} format
This commit is contained in:
@@ -6,6 +6,7 @@ from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
import aiofiles
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
from sqlalchemy import select
|
||||
@@ -407,7 +408,8 @@ async def list_tools(
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
registry = get_tool_registry()
|
||||
return registry.list_for_api()
|
||||
items = registry.list_for_api()
|
||||
return {"items": items, "total": len(items)}
|
||||
|
||||
|
||||
# ─── Chat Sessions ───
|
||||
@@ -717,8 +719,8 @@ async def upload_attachment(
|
||||
file_id = str(uuid.uuid4())
|
||||
safe_filename = file.filename or "unnamed"
|
||||
storage_path = str(ATTACHMENT_DIR / f"{file_id}_{safe_filename}")
|
||||
with open(storage_path, "wb") as f:
|
||||
f.write(content)
|
||||
async with aiofiles.open(storage_path, "wb") as f:
|
||||
await f.write(content)
|
||||
|
||||
attachment = AIChatAttachment(
|
||||
session_id=session.id,
|
||||
|
||||
@@ -12,6 +12,8 @@ import logging
|
||||
import uuid
|
||||
from typing import Any, AsyncGenerator
|
||||
|
||||
import aiofiles
|
||||
|
||||
import litellm
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -380,8 +382,8 @@ async def _extract_attachment_content(
|
||||
parts: list[str] = []
|
||||
for att in attachments:
|
||||
try:
|
||||
with open(att.storage_path, "rb") as f:
|
||||
content = f.read()
|
||||
async with aiofiles.open(att.storage_path, "rb") as f:
|
||||
content = await f.read()
|
||||
|
||||
text_content = ""
|
||||
mime = att.mime_type.lower()
|
||||
|
||||
Reference in New Issue
Block a user