Skip to content

feat: uv, Google API fixes#463

Merged
alexeyqu merged 4 commits into
masterfrom
dev
Jul 6, 2026
Merged

feat: uv, Google API fixes#463
alexeyqu merged 4 commits into
masterfrom
dev

Conversation

@alexeyqu

@alexeyqu alexeyqu commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

alexeyqu and others added 4 commits July 4, 2026 20:33
Replace the flat, unpinned-boundary requirements.txt (which mixed direct
runtime deps with transitive ones and a dead pylint/isort/black stack
already superseded by ruff) with pyproject.toml + uv.lock. Only actual
direct imports are declared; uv resolves and locks the full transitive
tree instead of storing it flat. Drops unused deps (vk_api, Pillow,
PyYAML, gspread) found to have no real usage in src/.

Updates Dockerfile, Dockerfile.dev, and CI to install via uv instead of
pip, and fixes .dockerignore to exclude .venv so local venvs don't get
copied into the image.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JR68hNjowTEaMRzVFRh8Yi
sheetfu and our own drive_client both call googleapiclient's central
discovery endpoint (www.googleapis.com/discovery/v1/...) on every
process start. That endpoint is currently blocking our Hetzner host's
IP with a generic anti-abuse 403, which crash-loops the bot on every
restart since AppContext init can't get past GoogleSheetsClient. The
per-API discovery endpoint ({api}.googleapis.com/\$discovery/rest)
responds fine and is Google's documented replacement.
Reverts the ad hoc discoveryServiceUrl monkeypatch from the previous
commit. Since v2.0, google-api-python-client ships static discovery
documents for public APIs and uses them by default when no custom
discoveryServiceUrl is passed - no network call at all in the normal
path. We were pinned to 1.9.1 (2020), which predates that feature and
always fetches discovery live on every process start. That live fetch
is what crash-looped the bot when Google's endpoint rate-limited us.

Verified offline (network calls forcibly blocked at the socket level)
that both SheetsService and DriveService build successfully with the
existing sheetfu/oauth2client code, unchanged.
The real bug behind the /help hang: TelegramSender and the Google/
Planka clients are synchronous and blocking, but every command handler
ran them directly inline inside the single asyncio event loop thread
that python-telegram-bot polls and dispatches updates on. A timeout
would only cap how long one bad call blocks things - the actual design
flaw is that ANY slow or stuck call there freezes command dispatch for
every chat, not just the one being handled, since there's nothing else
running on that thread to keep polling for new updates.

Route sync handler calls through a dedicated ThreadPoolExecutor
(_run_handler), awaited via loop.run_in_executor, so the event loop
stays free to keep dispatching other updates while a handler blocks on
I/O. Async handlers are awaited directly as before. Verified two 1s
sync handlers now run concurrently instead of serializing.
@alexeyqu alexeyqu merged commit 880d357 into master Jul 6, 2026
3 of 5 checks passed
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.

1 participant