Repository navigation
feat(runner): приём событий через /runner/ - #83
Merged
Merged
Conversation
Вместо опроса HTML-страниц раннер получает события так же, как сам сайт FunPay: один POST /runner/ на тик с объектами orders_counters и chat_bookmarks. Объект считается изменившимся, если FunPay прислал его с новым тегом, поэтому в простое тик стоит один JSON-запрос вместо 4-5 страниц. - Истории изменившихся чатов догружаются пачками chat_node (до 10 чатов на запрос), новые сообщения отбираются по ID. Оповещение FunPay определяется по автору 0, а не по тексту. - Страницы продаж, покупок и профиля загружаются только по сигналу: сменились счётчики или в чате появилось оповещение (оплата, подтверждение, возврат, отзыв), и только если на них есть хендлеры. Заказы сверяются по ID и статусу первой страницы и отдаются хендлерам раньше сообщений того же тика. - Прежний режим остаётся: start_polling(..., legacy_polling=True).
bymyforge
self-requested a review
September 27, 2026 07:35
Collaborator
|
Привет, сладкий код, но к сожалению я не могу работать в воскресенье, это опасно для нервов |
bymyforge
approved these changes
Sep 28, 2026
bymyforge
left a comment
Collaborator
There was a problem hiding this comment.
Привет, всё отлично. Код просмотрел, протестировал на реальных условиях, все события ловит. Тесты тоже работают, красавчик
Collaborator
|
На будущее. Было бы здорово разбивать такие большие изменения на несколько логических коммитов. Так проще ревьюить и откатывать при необходимости. Для этого пулл реквеста уже можно оставить как есть, но давай на следующий раз так делать? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что сделано
Приём событий через
POST /runner/, как у самого сайта FunPay. Раннер по-прежнему опрашивает FunPay раз вtimerсекунд, но вместо HTML-страниц (/chat/,/orders/trade,/users/<id>/,/orders/и/chat/?node=на каждый изменившийся чат) отправляет один JSON-запрос на тик. Хендлеры и вызовstart_pollingне меняются. Основная логика вfpx/classes/runner/subclasses/_updates.py(около 280 строк), остальное точечные изменения и тесты.POST /runner/с объектамиorders_countersиchat_bookmarksи тегами из прошлого ответа. Объект считается изменившимся, если FunPay прислал его с новым тегом. В простое изменений нет, и тик больше ничего не загружает.chat_node, до 10 чатов в одном запросе. Новые сообщения отбираются по ID, поэтому до хендлеров доходят все, в том числе несколько за тик. Оповещение FunPay распознаётся по автору0, а не по тексту, и вon_messageне попадает (как после fix(chat_runner): не терять сообщения покупателя #81).on_new_reviewпрофиль не открывается, без хендлеров покупок не открывается/orders/. Заказы сверяются по ID и статусу первой страницы продаж, смена даты в полночь событием не считается.on_new_orderвыставит состояние FSM, сообщение, пришедшее вместе с оплатой, обработается уже в нём./runner/, и первый тик сверяет их ещё раз, поэтому заказ, оплаченный во время старта, не теряется.message.answer()больше не открывает страницу чата: имя чата (users-...) приходит вchat_node.Прежний режим остался:
start_polling(..., legacy_polling=True). Если он не нужен, уберу в этом же PR. Если новый режим лучше сначала сделать опциональным, переключу значение по умолчанию.Нагрузка в простое: тик стоил 4 HTML-страницы (5, если у продаж есть вторая страница), теперь один JSON-запрос. При
timer=3это порядка 80 страниц в минуту против 20 запросов. Замерено на фейковом FunPay в обоих режимах. Новое сообщение добавляет 1 запрос на пачку до 10 чатов. Событие заказа добавляет страницу продаж и, как раньше,/orders/<id>/на каждый изменившийся заказ.Изменения поведения:
on_messageубрал устаревшую оговорку: одинаковые сообщения подряд тоже доходят до хендлеров, в прежнем режиме после fix(chat_runner): не терять сообщения покупателя #81 тоже.Как проверено:
test_updates_e2e.py): настоящиеRunner,RequestEngineи парсеры поверхhttpx.MockTransport, фейковый FunPay отвечает на/runner/по тегам. Сценарии: тик в простое стоит один запрос; два сообщения за тик; «Я оплатил заказ, где товар?»; новый чат; оплата и сообщение в одном тике; оплата и подтверждение за тик при неизменных счётчиках; полночь; ответ бота; отзыв; упавший запрос истории; 12 чатов загружаются двумя пачками; оплата во время прогрева; старые сообщения чата, которого не было в списке при запуске.UpdatesRunner, разбораchat_bookmarksиchat_nodeна реальной разметке оповещения (из fix(chat_runner): не терять сообщения покупателя #81), первой страницы продаж и покупок, выбора режима.POST /runner/(21.8 запроса в минуту приtimer=3). Сообщения покупателя дошли доon_message, автоответ продавца в хендлеры не попал. Оплата пришла вon_new_orderс вернымchat_id, подтверждение заказа и отзыв пришли в свои хендлеры. Отзыв нашёлся по оповещению в чате, счётчики он не меняет. Оповещения FunPay вon_messageне попадали. Возврат и покупки вживую не проверяли.Чек-лист перед отправкой
pytest: 687 passed на 3.10, 3.11 и 3.12, стресс-тесты проходят).ruff check .иruff format .).mypy fpx: новых ошибок нет, 8 было и до изменений). - Не обязательно