Skip to content

Commit 0d1c775

Browse files
authored
Add error handling support in dispatcher
1 parent 544c793 commit 0d1c775

1 file changed

Lines changed: 71 additions & 13 deletions

File tree

pyrogram/dispatcher.py

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020
import inspect
2121
import logging
2222
from collections import OrderedDict
23+
from operator import itemgetter
2324

2425
import pyrogram
2526
from pyrogram import utils
2627
from pyrogram.handlers import (
27-
CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler,
28+
Handler,
29+
ErrorHandler, CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler,
2830
UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler, PreCheckoutQueryHandler,
2931
ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler, StoryHandler,
3032
ShippingQueryHandler, MessageReactionHandler, MessageReactionCountHandler, ChatBoostHandler,
@@ -78,6 +80,7 @@ def __init__(self, client: "pyrogram.Client"):
7880

7981
self.updates_queue = asyncio.Queue()
8082
self.groups = OrderedDict()
83+
self.error_handlers_groups = OrderedDict()
8184

8285
async def message_parser(update, users, chats):
8386
connection_id = getattr(update, "connection_id", None)
@@ -294,17 +297,21 @@ async def stop(self, clear_handlers: bool = True):
294297

295298
log.info("Stopped %s HandlerTasks", self.client.workers)
296299

297-
def add_handler(self, handler, group: int):
300+
def add_handler(self, handler: Union[Handler, ErrorHandler], group: int):
298301
async def fn():
299302
for lock in self.locks_list:
300303
await lock.acquire()
301304

302305
try:
303-
if group not in self.groups:
304-
self.groups[group] = []
305-
self.groups = OrderedDict(sorted(self.groups.items()))
306-
307-
self.groups[group].append(handler)
306+
if isinstance(handler, ErrorHandler):
307+
self.error_handlers_groups.setdefault(group, []).append(handler)
308+
self.error_handlers_groups = OrderedDict(sorted(self.error_handlers_groups.items(), key=itemgetter(0)))
309+
else:
310+
if group not in self.groups:
311+
self.groups[group] = []
312+
self.groups = OrderedDict(sorted(self.groups.items()))
313+
314+
self.groups[group].append(handler)
308315
finally:
309316
for lock in self.locks_list:
310317
lock.release()
@@ -317,10 +324,22 @@ async def fn():
317324
await lock.acquire()
318325

319326
try:
320-
if group not in self.groups:
321-
raise ValueError(f"Group {group} does not exist. Handler was not removed.")
322-
323-
self.groups[group].remove(handler)
327+
if isinstance(handler, ErrorHandler):
328+
if group not in self.error_handlers_groups:
329+
raise ValueError(
330+
f"Group {group} does not exist in error handlers; "
331+
"Error handler was not removed"
332+
)
333+
334+
self.error_handlers_groups[group].remove(handler)
335+
336+
if not self.error_handlers_groups[group]:
337+
del self.error_handlers_groups[group]
338+
else:
339+
if group not in self.groups:
340+
raise ValueError(f"Group {group} does not exist. Handler was not removed.")
341+
342+
self.groups[group].remove(handler)
324343
finally:
325344
for lock in self.locks_list:
326345
lock.release()
@@ -382,11 +401,50 @@ async def handler_worker(self, lock):
382401
raise
383402
except pyrogram.ContinuePropagation:
384403
continue
385-
except Exception as e:
386-
log.exception(e)
404+
except Exception as exc:
405+
await self.handle_update_handler_exception(exc, handler, args)
387406

388407
break
389408
except pyrogram.StopPropagation:
390409
pass
391410
except Exception as e:
392411
log.exception(e)
412+
413+
async def handle_update_handler_exception(self, exc: Exception, update_handler: Handler, args: Tuple[Any, ...]) -> None:
414+
handled = False
415+
try:
416+
for group in self.error_handlers_groups.values():
417+
for handler in group:
418+
if not isinstance(exc, handler.exceptions):
419+
continue
420+
421+
try:
422+
if inspect.iscoroutinefunction(handler.callback):
423+
await handler.callback(
424+
exc, update_handler, self.client, *args
425+
)
426+
else:
427+
await self.client.loop.run_in_executor(
428+
self.client.executor, handler.callback,
429+
exc, update_handler, self.client, *args
430+
)
431+
except pyrogram.StopPropagation:
432+
handled = True
433+
raise
434+
except pyrogram.ContinuePropagation:
435+
handled = True
436+
continue
437+
except Exception:
438+
log.exception("Error handler raised an exception:")
439+
else:
440+
handled = True
441+
442+
break
443+
except pyrogram.StopPropagation:
444+
pass
445+
finally:
446+
if not handled:
447+
log.error(
448+
f"Unexpected exception raised in {type(update_handler).__name__}:",
449+
exc_info=(type(exc), exc, exc.__traceback__)
450+
)

0 commit comments

Comments
 (0)