perf: blocking synchronous file I/O on async event loop #92

Open
opened 2026-03-20 13:17:33 +00:00 by cal · 0 comments
Owner

Problem

Synchronous open() + json.load()/json.dump() calls block the entire event loop while waiting for disk I/O.

commands/gameplay/scorecard_tracker.pyload_data() / save_data()

  • Called from coroutines in the /scorebug hot path
  • Every scorecard read/write blocks the event loop

services/chart_service.py_load_charts() / _save_charts() (lines 48–103)

  • Load happens at startup, save on admin chart modification
  • Startup blocking delays bot readiness

Fix

Wrap with asyncio.to_thread():

async def load_data(self) -> dict:
    return await asyncio.to_thread(self._load_data_sync)

def _load_data_sync(self) -> dict:
    if not self.data_file.exists():
        return {"scorecards": {}}
    with open(self.data_file) as f:
        return json.load(f)

Or use aiofiles for a more idiomatic async approach.

Impact

MEDIUM — Scorecard tracker is on the scorebug hot path (3-minute update cycle). Chart service blocks startup.

## Problem Synchronous `open()` + `json.load()`/`json.dump()` calls block the entire event loop while waiting for disk I/O. ### `commands/gameplay/scorecard_tracker.py` — `load_data()` / `save_data()` - Called from coroutines in the `/scorebug` hot path - Every scorecard read/write blocks the event loop ### `services/chart_service.py` — `_load_charts()` / `_save_charts()` (lines 48–103) - Load happens at startup, save on admin chart modification - Startup blocking delays bot readiness ## Fix Wrap with `asyncio.to_thread()`: ```python async def load_data(self) -> dict: return await asyncio.to_thread(self._load_data_sync) def _load_data_sync(self) -> dict: if not self.data_file.exists(): return {"scorecards": {}} with open(self.data_file) as f: return json.load(f) ``` Or use `aiofiles` for a more idiomatic async approach. ## Impact **MEDIUM** — Scorecard tracker is on the scorebug hot path (3-minute update cycle). Chart service blocks startup.
cal added the
ai-working
label 2026-03-20 13:18:38 +00:00
cal removed the
ai-working
label 2026-03-20 13:21:32 +00:00
Claude added the
ai-working
label 2026-03-20 14:31:10 +00:00
Claude added the
status/in-progress
label 2026-03-20 14:35:02 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: cal/major-domo-v2#92
No description provided.