Skip to content

Fix Telegram client startup under uvicorn in Docker#6

Open
akang943578 wants to merge 1 commit into
subinps:mainfrom
akang943578:fix/asyncio-event-loop-docker
Open

Fix Telegram client startup under uvicorn in Docker#6
akang943578 wants to merge 1 commit into
subinps:mainfrom
akang943578:fix/asyncio-event-loop-docker

Conversation

@akang943578

@akang943578 akang943578 commented Jun 27, 2026

Copy link
Copy Markdown

Summary

Fixes #5 — backend bot client fails on Docker startup with Future attached to a different loop.

  • Defer Pyrogram Client creation until FastAPI lifespan runs (binds to uvicorn's event loop)
  • Import bot handlers after clients are built
  • Use telegram.tg_client in auth/streaming routers to avoid stale None imports
  • Mount session volume at /app/session instead of /app so image rebuilds are not masked

Test plan

  • docker compose up -d --build on clean volume
  • Backend starts without asyncio loop error
  • GET /api/auth/bot/info returns bot username
  • Bot /start and file upload (requires storage channel admin setup)

Made with Cursor

Summary by CodeRabbit

  • Bug Fixes

    • Improved app startup reliability by avoiding early initialization issues.
    • Made authentication and streaming more stable when connecting to Telegram services.
    • Fixed session storage so updates persist without hiding the rest of the app.
  • Chores

    • Updated container storage settings for cleaner, safer persistence.

Defer Pyrogram Client creation until the FastAPI lifespan runs so clients
bind to uvicorn's event loop instead of failing with "Future attached to a
different loop". Register bot handlers after clients are built, resolve
stale tg_client imports in auth/streaming routers, and mount the session
volume at /app/session so rebuilds are not masked by a persisted /app tree.

Fixes subinps#5

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Telegram client pool construction is moved from module-import time into a new build_clients() function called during app startup. Bot handler registration is deferred until after the pool exists. Routers switch from direct tg_client imports to telegram.tg_client module references. The Docker volume mount is narrowed from /app to /app/session.

Lazy Telegram Client Initialization

Layer / File(s) Summary
Lazy build_clients() and deferred handler registration
backend/app/telegram.py, backend/app/main.py
Top-level eager client pool construction is replaced by build_clients(), which creates the session directory, populates clients, and sets tg_client. start_telegram_client() calls build_clients() then imports bot to register handlers. The side-effect bot import is removed from main.py.
Routers updated to use module-level tg_client reference
backend/app/routers/auth.py, backend/app/routers/streaming.py
Both routers switch from from ..telegram import tg_client to from .. import telegram, accessing telegram.tg_client so they always read the lazily assigned module attribute at call time.
Docker volume mount scoped to /app/session
docker-compose.yml
telegram_session volume is mounted at /app/session instead of /app, with an added comment explaining that mounting over /app hides rebuilt backend code.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 No more loops in a tangle at dawn,
The client pool waits till the server is on.
Session files tucked in their tidy new place,
Handlers now register with startup-time grace.
A Future attached? Not today — hop along! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: fixing Telegram client startup in Docker under uvicorn.
Linked Issues check ✅ Passed Clients are now built during FastAPI lifespan on uvicorn's loop, which addresses the loop-mismatch startup failure in #5.
Out of Scope Changes check ✅ Passed The router updates, handler import move, and session mount change all support the startup fix and stay within scope.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/app/routers/streaming.py`:
- Around line 153-156: The thumbnail fallback in the streaming route is
swallowing all `download_media(...)` exceptions, which turns real
client/session/API errors into a misleading later “Thumbnail not found”
response. Update the exception handling in the thumbnail retrieval logic in
`streaming.py` to only suppress the expected not-found case, and add logging for
unexpected failures instead of using a bare `pass`. Keep the fix localized
around the `telegram.tg_client.download_media(...)` fallback path and the
surrounding response handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8cea2854-c397-4f8f-999d-53ccae561bf4

📥 Commits

Reviewing files that changed from the base of the PR and between 742a7a1 and 58e393c.

📒 Files selected for processing (5)
  • backend/app/main.py
  • backend/app/routers/auth.py
  • backend/app/routers/streaming.py
  • backend/app/telegram.py
  • docker-compose.yml
💤 Files with no reviewable changes (1)
  • backend/app/main.py

Comment on lines +153 to 156
thumb_bytes = await telegram.tg_client.download_media(file.thumbnail_file_id, in_memory=True)
return Response(content=thumb_bytes.getvalue(), media_type="image/jpeg")
except Exception:
pass

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Don’t turn fallback download failures into a fake 404.

Lines 153-156 swallow every download_media(...) failure, so client/session/API problems are silently converted into the later “Thumbnail not found” path. Please narrow this to the expected not-found case and log unexpected failures instead of pass.

🧰 Tools
🪛 Ruff (0.15.18)

[error] 155-156: try-except-pass detected, consider logging the exception

(S110)


[warning] 155-155: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/routers/streaming.py` around lines 153 - 156, The thumbnail
fallback in the streaming route is swallowing all `download_media(...)`
exceptions, which turns real client/session/API errors into a misleading later
“Thumbnail not found” response. Update the exception handling in the thumbnail
retrieval logic in `streaming.py` to only suppress the expected not-found case,
and add logging for unexpected failures instead of using a bare `pass`. Keep the
fix localized around the `telegram.tg_client.download_media(...)` fallback path
and the surrounding response handling.

Source: Linters/SAST tools

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.

Backend bot client fails on Docker startup: Future attached to a different loop

1 participant