refactor: replace async_helpers with BackgroundTasks and remove run_async_task
Merge Request
Overview
This MR refactors the async execution mechanism by removing the custom async helper (async_helpers.py) and replacing it with FastAPI’s built-in BackgroundTasks. This change improves reliability and eliminates event loop related errors.
What does this MR do and why?
Previously, the project used a custom utility (run_async_task) to execute async functions from sync contexts using manual event loop handling and threads. This approach was fragile and caused issues like "RuntimeError: This event loop is already running".
This MR replaces that implementation with FastAPI BackgroundTasks, ensuring safe background execution without blocking the API response and improving maintainability.
Changes Made
- Removed
app/utils/async_helpers.py - Removed all usages of
run_async_task - Added BackgroundTasks in route layer
- Removed all usages of
asyncio.run() - Removed
_broadcast_queue_update_sync()(sync fallback) - Updated async execution to pass coroutine directly using
background_tasks.add_task() - Made
background_tasksmandatory across service functions - Updated
consultation_queue_service.pyto supportbackground_tasks - Updated
doctor_service.pyto propagatebackground_tasks - Updated route files to inject and pass BackgroundTasks
- Simplified test assertions using
call_args.args[:3] - Updated existing tests to include
BackgroundTasks - Removed async_helpers related tests
- Verified no remaining references to async_helpers
Technical Details
Root Cause: Custom async helper manually handled event loops and threads, leading to instability and runtime errors.
Fix: Replaced custom async handling with FastAPI BackgroundTasks by passing coroutine functions directly, avoiding manual event loop control.
Flow: Route → BackgroundTasks → Service → Async Broadcast
Type of Change
-
🐛 Bug fix -
✨ New feature -
💥 Breaking change -
📝 Documentation update -
♻ ️ Refactor (no functional changes) -
⚡ Performance improvement -
🧪 Test update -
🔧 Configuration change -
🚨 Security fix -
🗑 ️ Deprecation
Related Issues / References
- Closes #77 (closed)
Screenshots or Screen Recordings
How to Validate Locally
-
Start server: docker compose up --build
-
Login and get token
-
Call: POST /api/v1/doctors/assign-doctor
-
Verify: GET /api/v1/queue/all
Expected:
- Patient assigned successfully
- Queue updated correctly
- No async errors in logs
Testing Done
-
API endpoint tests passing
Test Cases Covered:
| Scenario | Expected Result | Status |
|---|---|---|
| Assign doctor | Success response | |
| Queue update | Patient appears in queue | |
| Async handling | No event loop error |
Test Commands Run: pytest
Code Quality Checklist
-
No duplicate code -
Clean refactor -
No unused imports -
BackgroundTasks used correctly -
No API changes -
No runtime async errors
Documentation
-
README.md updated -
API docs updated
Known Limitations / Technical Debt
- Uses FastAPI BackgroundTasks for async execution; can be extended with
anyioif advanced async control is required in future
Additional Notes
- No changes to business logic
- Fully backward compatible
- Implementation follows FastAPI async best practices
MR Acceptance Checklist
-
Code works as intended -
No bugs introduced -
Clean and maintainable code
