fix: A21 phase 1 — 352 routes async sans await → threadpool (v7.8.0)
FlowDeck CI / lint (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 0s
FlowDeck CI / docker (push) Canceled after 0s

- Conversion `async def` → `def` de TOUTES les routes dont le corps ne contient
  ni `await`, ni `async with`, ni `async for`, ni `asyncio` (scan automatique
  corps par corps sur app/ : 352 converties, 0 dangereuses, vérifié
  `asyncio`/`run_coroutine`/`.result()` absents). FastAPI exécute ces handlers
  dans son threadpool → tout leur SQLite (`get_conn()` + `conn.execute`) quitte
  l'event loop, sans changer une ligne de logique.
- Répartition : api_v2 60, dashboard 40, collections 25, board 23,
  workspace 19, wiki 17, permissions 14, api 14, main.py 6, + 35 fichiers.
- Les 4 routers prioritaires de l'audit sont couverts par ce lot :
  api_v2 60 + dashboard 40 + collections 25 + board 23 = 148 conversions
  (le reste de leurs routes attend la phase 2 : elles ont de vrais `await`).
- Reste (phase 2) : les 311 routes avec de vrais `await` → enrouler les blocs
  DB dans `await anyio.to_thread.run_sync(...)` ; pas de wrapper partagé livré
  (rien ne l'appellerait — YAGNI jusqu'au premier usage).

suite **1037/1037** (233 s) · `ruff check app tests` OK · docs à jour
This commit is contained in:
2026-10-01 10:53:26 -04:00
parent c718fe06de
commit 224bda74d5
48 changed files with 379 additions and 358 deletions
+6 -6
View File
@@ -71,7 +71,7 @@ def _validate_payload(body: dict) -> None:
@router.get("/workspace/automations")
async def list_automations(request: Request):
def list_automations(request: Request):
with get_conn() as conn:
rows = conn.execute("SELECT * FROM automations ORDER BY created_at DESC").fetchall()
items = [dict(r) for r in rows]
@@ -109,7 +109,7 @@ async def create_automation(request: Request):
@router.get("/workspace/automations/{auto_id}")
async def get_automation(request: Request, auto_id: int):
def get_automation(request: Request, auto_id: int):
with get_conn() as conn:
row = conn.execute("SELECT * FROM automations WHERE id=?", (auto_id,)).fetchone()
if not row:
@@ -147,7 +147,7 @@ async def update_automation(request: Request, auto_id: int):
@router.delete("/workspace/automations/{auto_id}")
async def delete_automation(request: Request, auto_id: int):
def delete_automation(request: Request, auto_id: int):
with get_conn() as conn:
conn.execute("DELETE FROM automations WHERE id=?", (auto_id,))
conn.commit()
@@ -178,7 +178,7 @@ async def run_automation_button(request: Request, auto_id: int):
@router.get("/workspace/automations/{auto_id}/runs")
async def automation_runs_history(request: Request, auto_id: int, limit: int = 50):
def automation_runs_history(request: Request, auto_id: int, limit: int = 50):
with get_conn() as conn:
rows = conn.execute(
"""SELECT * FROM automation_runs WHERE automation_id=?
@@ -226,7 +226,7 @@ def _encrypt_step_config(config: dict) -> dict:
@router.get("/workspace/automations/{auto_id}/steps")
async def list_steps(request: Request, auto_id: int):
def list_steps(request: Request, auto_id: int):
if _get_auto(auto_id) is None:
return _auto_404()
return {"automation_id": auto_id, "steps": get_steps(auto_id)}
@@ -279,7 +279,7 @@ async def update_step(request: Request, step_id: int):
@router.delete("/workspace/automations/steps/{step_id}")
async def delete_step(request: Request, step_id: int):
def delete_step(request: Request, step_id: int):
_require_session(request)
with get_conn() as conn:
conn.execute("DELETE FROM automation_steps WHERE id=?", (step_id,))