любое событие в ТГ -> новый апдейт
вот пришел апдейт, аиограм начинает его обрабатывать
опустим некоторые детали и вот начинается пробежка по хендлерам
каждый хендлер имеет набор фильтров, аиограм перебирает хендлеры, пока все фильтры этого хендлера не вернут
не False
Допустим у тебя фильтры на то, находится ли юзер в канале. Делать этот запрос в каждом фильтре нельзя, так как сразу влетишь по лимитам. Почему? Потому что даже если фильтры одинаковые, то они отрабатывают заново в каждом хендлере.
Пример фильтра:
async def in_channel(message: types.Message):
return (await bot.get_chat_member(..., message.from_user.id)).status != "status"
Теперь представим, что этот фильтр в 100 хендлерах. Естественно, это не единственный фильтр в этих 100 хендлерах, везде применяются разные state, возможно разные команды. Аиограм отрабатывает этот фильтр на всех 100 хендлерах пока все фильтры хендлера не вернут
не False
.
Пофантазируем ещё: поступило сообщение, и так произошло, что его обработает только сотый хендлер. Сообщение всего одно, от одного пользователя, а мы 100 раз обратились к апи менее чем за секунду.
Появляется идея кешировать результат обращения к апи, чтобы не обращаться к нему каждый раз. Как это сделать? В фильтры и мидлвари передается объект одного из типов обновления (сообщение, колбек и т.д), у каждого есть
проперти conf в которую можно пихать всякое полезное. Запихаем туда результат из апи.
Перепишем наш фильтр так, чтобы результат из апи сохранялся на время обрабтки запроса:
async def in_channel(message: types.Message):
cache_member = message.conf.get("member")
if cache_member is None:
cache_member = message.conf["member"] = await bot.get_chat_member(..., message.from_user.id)
return cache_member.status != "status"
Теперь, даже если обработает запрос только сотый хендлер, запрос к апи будет всего один раз. Это возможно, так как в фильтры передается ссылка на сообщение, а не копия.