diff --git a/CHANGES/1331.misc b/CHANGES/1331.misc new file mode 100644 index 00000000..375f975c --- /dev/null +++ b/CHANGES/1331.misc @@ -0,0 +1 @@ +Prevent update handling task pointers from being garbage collected, backport from 2.x \ No newline at end of file diff --git a/aiogram/dispatcher/dispatcher.py b/aiogram/dispatcher/dispatcher.py index 827b300a..e3eb654a 100644 --- a/aiogram/dispatcher/dispatcher.py +++ b/aiogram/dispatcher/dispatcher.py @@ -6,7 +6,7 @@ import signal import warnings from asyncio import CancelledError, Event, Future, Lock from contextlib import suppress -from typing import Any, AsyncGenerator, Dict, List, Optional, Union +from typing import Any, AsyncGenerator, Dict, List, Optional, Set, Union from .. import loggers from ..client.bot import Bot @@ -95,6 +95,7 @@ class Dispatcher(Router): self._running_lock = Lock() self._stop_signal: Optional[Event] = None self._stopped_signal: Optional[Event] = None + self._handle_update_tasks: Set[asyncio.Task[Any]] = set() def __getitem__(self, item: str) -> Any: return self.workflow_data[item] @@ -349,7 +350,9 @@ class Dispatcher(Router): ): handle_update = self._process_update(bot=bot, update=update, **kwargs) if handle_as_tasks: - asyncio.create_task(handle_update) + handle_update_task = asyncio.create_task(handle_update) + self._handle_update_tasks.add(handle_update_task) + handle_update_task.add_done_callback(self._handle_update_tasks.discard) else: await handle_update finally: diff --git a/aiogram/webhook/aiohttp_server.py b/aiogram/webhook/aiohttp_server.py index bf9f2aaf..7caa0e15 100644 --- a/aiogram/webhook/aiohttp_server.py +++ b/aiogram/webhook/aiohttp_server.py @@ -2,7 +2,7 @@ import asyncio import secrets from abc import ABC, abstractmethod from asyncio import Transport -from typing import Any, Awaitable, Callable, Dict, Optional, Tuple, cast +from typing import Any, Awaitable, Callable, Dict, Optional, Set, Tuple, cast from aiohttp import MultipartWriter, web from aiohttp.abc import Application @@ -98,6 +98,7 @@ class BaseRequestHandler(ABC): self.dispatcher = dispatcher self.handle_in_background = handle_in_background self.data = data + self._background_feed_update_tasks: Set[asyncio.Task[Any]] = set() def register(self, app: Application, /, path: str, **kwargs: Any) -> None: """ @@ -139,11 +140,13 @@ class BaseRequestHandler(ABC): await self.dispatcher.silent_call_request(bot=bot, result=result) async def _handle_request_background(self, bot: Bot, request: web.Request) -> web.Response: - asyncio.create_task( + feed_update_task = asyncio.create_task( self._background_feed_update( bot=bot, update=await request.json(loads=bot.session.json_loads) ) ) + self._background_feed_update_tasks.add(feed_update_task) + feed_update_task.add_done_callback(self._background_feed_update_tasks.discard) return web.json_response({}, dumps=bot.session.json_dumps) def _build_response_writer(