feat: fetch для user и chat при auto_requests=False#101
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Pending LazyRef является falsy (bool = False), поэтому паттерн `if event.chat` не вызовет fetch(). Исправлено на `is not None`. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@Olegt0rr привет! Оцени, пожалуйста) |
Olegt0rr
left a comment
There was a problem hiding this comment.
Крутая и полезная идея, т.к. я как раз хочу с ростом нагрузки на мой проект перейти в режим отключения авто-реквестов и возникает много вопросов.
Есть несколько идей по оптимизации логики - написал точечно
| async def fetch_from_user(self) -> Any | None: | ||
| """Явно получить from_user для события, если доступен lazy fetch.""" | ||
|
|
||
| from_user = self.from_user | ||
| if from_user is None: | ||
| return None | ||
|
|
||
| fetch = getattr(from_user, "fetch", None) | ||
| if callable(fetch): | ||
| return await fetch() | ||
|
|
||
| return from_user |
There was a problem hiding this comment.
Есть ощущение, что этак конструкция адекватна для любого LazyRef поля и можно ещё унифицировать, не создавая отдельный метод для каждого поля
There was a problem hiding this comment.
Pull request overview
PR добавляет явный механизм “ленивого” получения event.chat и event.from_user при bot.auto_requests=False, чтобы избежать скрытых API-запросов и при этом сохранить удобный способ догрузки данных по требованию.
Changes:
- Добавлены lazy ref-объекты
ChatRef/FromUserRefи общий.fetch()API для уже-разрешённых моделей черезFetchableMixin. enrich_event()теперь всегда инжектитbot, а приauto_requests=Falseприкрепляет lazy refs вместо сетевых запросов.- Добавлены/расширены тесты на поведение lazy refs и
enrich_event(auto_requests=False), обновлена документация с примерами.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| maxapi/types/fetchable.py | Новые LazyRef, ChatRef, FromUserRef и FetchableMixin для унифицированного fetch() |
| maxapi/utils/updates.py | Логика attach lazy refs при auto_requests=False, рефакторинг извлечения chat_id/from_user |
| maxapi/types/updates/base_update.py | Добавлены fetch_chat()/fetch_from_user() для явной догрузки |
| maxapi/types/users.py | User теперь поддерживает fetch() через FetchableMixin |
| maxapi/types/chats.py | Chat теперь поддерживает fetch() через FetchableMixin |
| maxapi/types/init.py | Экспорт ChatRef/FromUserRef в публичный API types |
| maxapi/types/attachments/video.py | Уточнение TYPE_CHECKING-аннотации bot |
| tests/test_fetchable_refs.py | Новый тестовый набор для LazyRef и методов BaseUpdate.fetch_* |
| tests/test_enrich_event.py | Новые интеграционные тесты для auto_requests=False и lazy refs |
| maxapi/bot.py | Докстринг: описание поведения auto_requests=False |
| docs/examples.md | Документация/примеры по явному fetch_* и .fetch() |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async def fetch(self) -> ResolvedValue | None: | ||
| """Загрузить значение и закешировать результат.""" | ||
|
|
||
| if self._resolved is _UNSET: | ||
| value = await self._fetcher() | ||
| self._resolved = value | ||
| self._setter(value) | ||
|
|
||
| return cast(ResolvedValue | None, self._resolved) |
There was a problem hiding this comment.
LazyRef.fetch() is not concurrency-safe: if two coroutines call fetch() одновременно, оба могут увидеть _resolved == _UNSET и запустить fetcher дважды, а setter будет вызван два раза. Лучше защитить первую загрузку asyncio.Lock/Task-кэшированием (например, хранить _fetch_task и await его) чтобы гарантировать ровно один сетевой вызов и один setter.
Olegt0rr
left a comment
There was a problem hiding this comment.
Очень хорошие замечания написал Copilot (по поводу гонки с несколькими запросами - особенно)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Подтянуты PR из upstream: love-apples#93 (FSM), love-apples#96 (download_file), love-apples#101 (fetch user/chat), love-apples#105 (ClipboardButton), love-apples#109 (share payload), love-apples#110 (webhook secret warning). Конфликт в tests/test_types.py: принят upstream-стиль (явный update_type, разнесённые assert). Сохранены доп. тесты test_get_ids_ignores_inviter_id / test_get_ids_ignores_admin_id — их purpose именно цель PR love-apples#94 (не путать inviter_id/admin_id с user.user_id).
Если бот создан с
auto_requests=False, тоevent.chatиevent.from_userмогут быть lazy ref. В этом режиме запрашиваем ихявно: