Skip to content

Stop the fly proxy from shutting the bot down (#95) The app declared an http service on port 8080 with autostop enabled, but a long polling bot never listens on a port. The proxy therefore cordoned and stopped the machine roughly five minutes after every start, and autostart could not bring it back because no traffic ever reaches the app. Drop the service section so the worker simply runs. Also raise kill_timeout to 30s, which the graceful shutdown now needs, record the 768MB the machine already runs with, and remove the obsolete experimental block left over from the 2022 nomad config. - #96

Merged
NickLyrick merged 16 commits into
stagefrom
dev
Aug 9, 2026

Conversation

@NickLyrick

Copy link
Copy Markdown
Owner

No description provided.

slipmetal and others added 16 commits June 1, 2024 19:43
* Added actions for like dev branches

* Added config for pylint

* Set RC for pylint

* Remove extra options for pylint

* Fixed pylint RC file

* Set checkout version to 4

* Rework run linters

* Run pylint without set rcfile

* ls folder

* Install requirements

* Disabled several options

* Enable cache for pip

* linter fixes

* linter fixes 2

* disable not-callable

* Add blank line

* fix survey string

* Add space

* return error handlers

* fix None args in set_date and set_delta

* disable duplicate-code

---------

Co-authored-by: Artem Kopytin <a.kopytin@antisleep.ru>
Co-authored-by: Aleksandr Kirilkin <sanekkirilkin@gmail.com>
Editors on Windows hosts were rewriting the whole tree to CRLF, which
turned 32 unrelated files into noise in every diff. Normalize on LF at
the git level and mirror it in the editor config.
Describe the trophy submission, avatar rotation and monthly survey flow,
the command reference, configuration, installation, project layout,
database schema and the Fly.io deployment pipeline.
A Python 3.12 container with a PostgreSQL service, so the bot can be run
against a local database without installing anything on the host.
get_chat_settings() asked for exactly one *Default* record, so the query
raised NoResultFound in every chat where no default avatar had been set.
The bot session used to be closed twice through asyncio.run() on an
already closed loop, and neither the scheduler nor the connection pool
was released at all. Close the session in a finally block, release both
resources from a dispatcher shutdown hook, and let Request own its
engine so it can be disposed and rebuilt.

Reconnection is now verified instead of assumed: check_db_connection()
re-runs the probe query after reconnecting and reports the outcome, and
the engine is created with pool_pre_ping so stale connections are
detected before a query uses them.
get_avatar() removed the record as part of reading it, so a failure in
set_chat_photo or send_photo — losing admin rights, for instance — threw
the trophy away without ever showing it. Return the record id instead and
delete it from change_avatar once the rotation has actually succeeded;
a failed rotation now simply retries on the next tick.

The result is returned as a QueuedAvatar named tuple: six positional
values, three of them strings in a row, were easy to unpack wrongly.
change_avatar() persisted the next date but never updated where_run, so
every rotation kept computing the interval from the same original date.
A malformed date or a non-numeric interval raised straight out of the
handler; both now answer with the expected format. /history no longer
falls back to the caller's username, which returned nothing for users
who have none — it looks the caller up by user id instead.
/set_date passes no interval and /set_delta passes no date, but the
missing half was only filled in when a job already existed. For a chat
that had no job yet — start() skips chats the bot was not a member of at
boot — /set_date reached IntervalTrigger with days=None and raised
TypeError. A partially filled where_run entry was just as fatal later,
since change_avatar adds delta to date unguarded.

Resolve both values against the stored state before branching, falling
back to now and to DEFAULT_DELTA, and always write the entry back whole.

This adds the first tests to the project, so it also brings the pytest
setup: the root conftest supplies the environment variables that
src.bot.settings reads at import time.
Also install the native libraries WeasyPrint and pdf2image need: the
lint step only parsed the sources, while the tests import them.
CI resolved pylint 3.3 from the compatible-release range while the dev
container ships 4.0.6, and the two disagree about R0917: 3.3 counts self
as a positional argument, 4.0 does not, so three signatures that pass
locally failed the lint step. Pin all three dev tools exactly.
The root carries an __init__.py, so pytest treats it as a package and
inserts its parent directory instead of the root itself. `import src`
therefore only resolved under `python -m pytest`, which injects the cwd
on its own; the bare `pytest` that CI runs failed to collect at all.
aiogram 3.5 -> 3.30 brings two breaking changes that the code had to
follow: Bot() no longer takes parse_mode, so the default now goes through
DefaultBotProperties, and Telegram models are frozen, so the media
caption is set at construction instead of being assigned afterwards.

Also declare python-dateutil, which jobs.py imports directly and which
only arrived as a transitive dependency of pandas, and drop the typing
backport — it targets Python below 3.5 and has no business in a 3.12
image.
The app declared an http service on port 8080 with autostop enabled, but
a long polling bot never listens on a port. The proxy therefore cordoned
and stopped the machine roughly five minutes after every start, and
autostart could not bring it back because no traffic ever reaches the
app. Drop the service section so the worker simply runs.

Also raise kill_timeout to 30s, which the graceful shutdown now needs,
record the 768MB the machine already runs with, and remove the obsolete
experimental block left over from the 2022 nomad config.
@NickLyrick
NickLyrick requested a review from slipmetal August 9, 2026 14:20
@NickLyrick
NickLyrick merged commit 1053108 into stage Aug 9, 2026
1 check passed
NickLyrick added a commit that referenced this pull request Aug 9, 2026
Merge pull request #96 from NickLyrick/dev

Stop the fly proxy from shutting the bot down (#95)

The app declared an http service on port 8080 with autostop enabled, but
a long polling bot never listens on a port. The proxy therefore cordoned
and stopped the machine roughly five minutes after every start, and
autostart could not bring it back because no traffic ever reaches the
app. Drop the service section so the worker simply runs.

Also raise kill_timeout to 30s, which the graceful shutdown now needs,
record the 768MB the machine already runs with, and remove the obsolete
experimental block left over from the 2022 nomad config.
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.

2 participants