Skip to content

Fix Python SDK timer: use async loop#82

Merged
Divkix merged 1 commit into
mainfrom
opencode/issue74-20260511044925
May 11, 2026
Merged

Fix Python SDK timer: use async loop#82
Divkix merged 1 commit into
mainfrom
opencode/issue74-20260511044925

Conversation

@opencode-agent
Copy link
Copy Markdown
Contributor

Plan

  1. Root cause: BatchQueue uses threading.Timer for interval-based flushes. The timer fires in a daemon thread with no running event loop, so _on_timer_expired falls back to asyncio.run(self.flush()) — creating and destroying a new event loop on every flush. This breaks httpx.AsyncClient connection pool reuse and wastes resources.
  2. Fix strategy: Replace threading.Timer with a dedicated background event loop thread (_queue_loop + _queue_thread). All flush work (timer-triggered and batch-triggered from sync contexts) is submitted to this single persistent loop via asyncio.run_coroutine_threadsafe(). The public flush() method dispatches to the background loop and awaits the result with asyncio.wrap_future().
  3. Test impact: Two unit tests used asyncio.Event inside mock send_batch functions. Because the mock now runs in the background loop, those events were tied to the wrong loop. Updated those tests to use threading.Event with polling loops.

What Changed

sdks/python/src/logwell/queue.py

  • Added a persistent background event loop thread (_ensure_loop, _run_loop, _stop_loop).
  • Replaced threading.Timer with an asyncio-based timer (_timer_coro) that sleeps and then schedules flushes on the background loop.
  • Refactored flush() into a dispatcher that routes to the background loop, and _do_flush() that contains the actual logic.
  • _trigger_flush() now always submits work to the background loop instead of calling asyncio.run().

sdks/python/tests/unit/test_queue.py

  • test_concurrent_flush_prevented and test_entries_added_during_flush_are_preserved: replaced asyncio.Event with threading.Event + polling loops so the mock send_batch works correctly when executed in the background loop.

Verification

  • All 308 Python SDK tests pass (286 unit + 22 integration).
  • Lint (ruff) and type check (mypy) both pass.

Closes #74

New%20session%20-%202026-05-11T04%3A49%3A25.154Z
opencode session  |  github run

Co-authored-by: Divkix <Divkix@users.noreply.github.com>
@Divkix Divkix merged commit 30a8ffa into main May 11, 2026
14 of 16 checks passed
@Divkix Divkix deleted the opencode/issue74-20260511044925 branch May 11, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[LOW] Python SDK Threading.Timer creates new asyncio event loop per flush

1 participant