fix(migrations): improve async migration handling by adapting to existing event loops#1094
Conversation
…ting event loops Signed-off-by: Mykyta Yaromenko <m-freelance@outlook.com>
There was a problem hiding this comment.
Pull request overview
This PR updates Alembic’s async-migration dispatcher in env.py to avoid attempting asyncio.run() when an event loop is already active, addressing failures seen in environments where a loop is running (e.g., nest_asyncio + uvloop) and preventing “cannot reuse already awaited coroutine” retry issues.
Changes:
- Switch migration execution-path selection from exception-driven fallback to an upfront
asyncio.get_running_loop()check. - Always offload async migrations to a dedicated thread when a loop is already running; otherwise use
asyncio.run().
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6d470d26be
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…event loops Signed-off-by: Mykyta Yaromenko <m-freelance@outlook.com>
…ndant error checks Signed-off-by: Mykyta Yaromenko <m-freelance@outlook.com>
ruff format + one unused-import fix so the fork branch passes the static checks that don't run on fork PRs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A2bgrGfWiL4izcjj66u9R8 Signed-off-by: phernandez <paul@basicmachines.co>
Summary
Replace the error-catch approach in
_run_async_engine_migrationswith proactive loop detection, and remove the now-unusedis_running_loop_errorhelper frommigration_loop.py.Problem
The previous implementation called
asyncio.run()and caught the resultingRuntimeErrorto detect an already-running event loop, then fell back to a thread-based migration path. This approach:RuntimeErrors that matched neither known message patternChanges
src/basic_memory/alembic/env.py_loop_is_running()helper that proactively callsasyncio.get_running_loop()to check loop state before attempting migrations_run_async_engine_migrations()to branch on_loop_is_running()up front:_run_async_migrations_in_thread()(safe thread offload)_run_async_migrations_with_asyncio_run()directly, letting unexpected errors propagatesrc/basic_memory/migration_loop.pyis_running_loop_error()— no longer neededtests/test_alembic_env.py/tests/test_migration_loop.py_loop_is_running()and the new branch logicis_running_loop_errorhelperTesting