From 835968e8fee9e83086f3d50cf139a957f6997ad6 Mon Sep 17 00:00:00 2001 From: Davide Scaini Date: Tue, 19 May 2026 19:53:26 +0200 Subject: [PATCH] perf: unblock event loop for segment_efforts scan Extract the synchronous segment-file scan into a plain function and dispatch it via asyncio.to_thread so it runs in a thread pool instead of blocking the event loop during concurrent fetches. --- bincio/serve/routers/activities.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/bincio/serve/routers/activities.py b/bincio/serve/routers/activities.py index e120c53..143021b 100644 --- a/bincio/serve/routers/activities.py +++ b/bincio/serve/routers/activities.py @@ -351,13 +351,16 @@ async def activity_segment_efforts( bincio_session: str | None = Cookie(default=None), ) -> JSONResponse: """Return segment efforts that belong to a specific activity for the logged-in user.""" + import asyncio from bincio.segments import store as _seg_store user = deps._require_user(bincio_session) dd = deps._get_data_dir() - efforts_dir = dd / user.handle / "segment_efforts" - result = [] - if efforts_dir.exists(): - import json as _json + + def _collect() -> list[dict]: + efforts_dir = dd / user.handle / "segment_efforts" + result: list[dict] = [] + if not efforts_dir.exists(): + return result for ef_file in sorted(efforts_dir.glob("*.json")): seg_id = ef_file.stem all_efforts = _seg_store.load_efforts(dd, user.handle, seg_id) @@ -370,11 +373,13 @@ async def activity_segment_efforts( pr_elapsed = min(e.elapsed_s for e in all_efforts) for eff in matching: result.append({ - "segment_id": seg.id, - "segment_name": seg.name, - "segment_distance_m": seg.distance_m, - "elapsed_s": eff.elapsed_s, - "pr_elapsed_s": pr_elapsed, - "started_at": _seg_store._iso(eff.started_at), + "segment_id": seg.id, + "segment_name": seg.name, + "segment_distance_m": seg.distance_m, + "elapsed_s": eff.elapsed_s, + "pr_elapsed_s": pr_elapsed, + "started_at": _seg_store._iso(eff.started_at), }) - return JSONResponse(result) + return result + + return JSONResponse(await asyncio.to_thread(_collect))