mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-12 18:19:34 +00:00
More annotations and add warning.
This commit is contained in:
parent
0b21996b87
commit
6696c8e9ad
3 changed files with 54 additions and 7 deletions
|
|
@ -715,6 +715,21 @@ class Dispatcher:
|
||||||
return FSMContext(storage=self.storage, chat=chat, user=user)
|
return FSMContext(storage=self.storage, chat=chat, user=user)
|
||||||
|
|
||||||
def async_task(self, func):
|
def async_task(self, func):
|
||||||
|
"""
|
||||||
|
Execute handler as task and return None.
|
||||||
|
Use that decorator for slow handlers (with timeouts)
|
||||||
|
|
||||||
|
.. code-block:: python3
|
||||||
|
|
||||||
|
@dp.message_handler(commands=['command'])
|
||||||
|
@dp.async_task
|
||||||
|
async def cmd_with_timeout(message: types.Message):
|
||||||
|
await asyncio.sleep(120)
|
||||||
|
return SendMessage(message.chat.id, 'KABOOM').reply(message)
|
||||||
|
|
||||||
|
:param func:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
def process_response(task):
|
def process_response(task):
|
||||||
response = task.result()
|
response = task.result()
|
||||||
self.loop.create_task(response.execute_response(self.bot))
|
self.loop.create_task(response.execute_response(self.bot))
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import asyncio
|
||||||
import asyncio.tasks
|
import asyncio.tasks
|
||||||
import datetime
|
import datetime
|
||||||
import functools
|
import functools
|
||||||
import time
|
|
||||||
import typing
|
import typing
|
||||||
from typing import Union, Dict, Optional
|
from typing import Union, Dict, Optional
|
||||||
|
|
||||||
|
|
@ -12,6 +11,8 @@ from .. import types
|
||||||
from ..bot import api
|
from ..bot import api
|
||||||
from ..bot.base import Integer, String, Boolean, Float
|
from ..bot.base import Integer, String, Boolean, Float
|
||||||
from ..utils import json
|
from ..utils import json
|
||||||
|
from ..utils.deprecated import warn_deprecated as warn
|
||||||
|
from ..utils.exceptions import TimeoutWarning
|
||||||
from ..utils.payload import prepare_arg
|
from ..utils.payload import prepare_arg
|
||||||
|
|
||||||
DEFAULT_WEB_PATH = '/webhook'
|
DEFAULT_WEB_PATH = '/webhook'
|
||||||
|
|
@ -41,10 +42,6 @@ class WebhookRequestHandler(web.View):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, request):
|
|
||||||
self._start_time = time.time()
|
|
||||||
super(WebhookRequestHandler, self).__init__(request)
|
|
||||||
|
|
||||||
def get_dispatcher(self):
|
def get_dispatcher(self):
|
||||||
"""
|
"""
|
||||||
Get Dispatcher instance from environment
|
Get Dispatcher instance from environment
|
||||||
|
|
@ -85,9 +82,19 @@ class WebhookRequestHandler(web.View):
|
||||||
return web.Response(text='ok')
|
return web.Response(text='ok')
|
||||||
|
|
||||||
async def process_update(self, update):
|
async def process_update(self, update):
|
||||||
|
"""
|
||||||
|
Need respond in less than 60 seconds in to webhook.
|
||||||
|
|
||||||
|
So... If you respond greater than 55 seconds webhook automatically respond 'ok'
|
||||||
|
and execute callback response via simple HTTP request.
|
||||||
|
|
||||||
|
:param update:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
dispatcher = self.get_dispatcher()
|
dispatcher = self.get_dispatcher()
|
||||||
loop = dispatcher.loop
|
loop = dispatcher.loop
|
||||||
|
|
||||||
|
# Analog of `asyncio.wait_for` but without cancelling task
|
||||||
waiter = loop.create_future()
|
waiter = loop.create_future()
|
||||||
timeout_handle = loop.call_later(RESPONSE_TIMEOUT, asyncio.tasks._release_waiter, waiter)
|
timeout_handle = loop.call_later(RESPONSE_TIMEOUT, asyncio.tasks._release_waiter, waiter)
|
||||||
cb = functools.partial(asyncio.tasks._release_waiter, waiter)
|
cb = functools.partial(asyncio.tasks._release_waiter, waiter)
|
||||||
|
|
@ -107,11 +114,22 @@ class WebhookRequestHandler(web.View):
|
||||||
return fut.result()
|
return fut.result()
|
||||||
else:
|
else:
|
||||||
fut.remove_done_callback(cb)
|
fut.remove_done_callback(cb)
|
||||||
fut.add_done_callback(self.response_task)
|
fut.add_done_callback(self.respond_via_request)
|
||||||
finally:
|
finally:
|
||||||
timeout_handle.cancel()
|
timeout_handle.cancel()
|
||||||
|
|
||||||
def response_task(self, task):
|
def respond_via_request(self, task):
|
||||||
|
"""
|
||||||
|
Handle response after 55 second.
|
||||||
|
|
||||||
|
:param task:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
warn(f"Detected slow response into webhook. "
|
||||||
|
f"(Greater than {RESPONSE_TIMEOUT} seconds)\n"
|
||||||
|
f"Recommended to use 'async_task' decorator from Dispatcher for handler with long timeouts.",
|
||||||
|
TimeoutWarning)
|
||||||
|
|
||||||
dispatcher = self.get_dispatcher()
|
dispatcher = self.get_dispatcher()
|
||||||
loop = dispatcher.loop
|
loop = dispatcher.loop
|
||||||
|
|
||||||
|
|
@ -121,6 +139,12 @@ class WebhookRequestHandler(web.View):
|
||||||
asyncio.ensure_future(response.execute_response(self.get_dispatcher().bot), loop=loop)
|
asyncio.ensure_future(response.execute_response(self.get_dispatcher().bot), loop=loop)
|
||||||
|
|
||||||
def get_response(self, results):
|
def get_response(self, results):
|
||||||
|
"""
|
||||||
|
Get response object from results.
|
||||||
|
|
||||||
|
:param results: list
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
if results is None:
|
if results is None:
|
||||||
return None
|
return None
|
||||||
for result in results:
|
for result in results:
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,14 @@ class TelegramAPIError(Exception):
|
||||||
super(TelegramAPIError, self).__init__(_clean_message(message))
|
super(TelegramAPIError, self).__init__(_clean_message(message))
|
||||||
|
|
||||||
|
|
||||||
|
class AIOGramWarning(Warning):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TimeoutWarning(AIOGramWarning):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ValidationError(TelegramAPIError):
|
class ValidationError(TelegramAPIError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue