示例#1
0
 async def task_handler(self, handler, event, user):
     try:
         log.info(
             f'create task with timeout for user[{user}] event[{event.id}]')
         await asyncio.wait_for(handler.handle(event, self, user),
                                timeout=self.bot.task_timeout_s)
     except asyncio.TimeoutError:
         log.info(
             "task for user[{user_id}] with eventId[{event_id}] cancelled by timeout ({s})s"
             .format(user_id=user.id,
                     event_id=event.id,
                     s=self.bot.task_timeout))
     except asyncio.CancelledError:
         log.info(
             f"task for user[{user.id}] with eventId[{event.id}] cancelled'"
         )
     except Exception as e:
         log.exception(e)
     finally:
         log.info(f'finally task for {user}')
         user.handler = None
         while not user.events.empty():
             remaining_event = await user.events.get()
             log.info(
                 f'move event {remaining_event.id} from user[{user.id}] queue into bot queue'
             )
             await self.bot.events.put(remaining_event)
示例#2
0
 async def handle(self, event, dispatcher, user=None):
     if self.callback:
         log.info(f"call '{self.callback.__name__}' via '{self.__class__.__name__}'")
         kwargs = {'bot': dispatcher.bot, 'event': event}
         if user:
             kwargs['user'] = user
         await self.callback(**kwargs)
示例#3
0
 async def stop_polling(self):
     log.info('stop polling')
     self.is_polling = False
     if isinstance(self._polling_task, Task):
         self._polling_task.cancel()
     if isinstance(self._dispatcher_task, Task):
         self._dispatcher_task.cancel()
     self._polling_task = None
     self._dispatcher_task = None
示例#4
0
 async def start_polling(self):
     for item, message in ((self.is_polling, 'polling already run'),
                           (self._polling_task,
                            'polling task already exists'),
                           (self._dispatcher_task,
                            'dispatcher task already exists')):
         if item:
             log.warning(message)
             break
     else:
         log.info('start polling')
         self.is_polling = True
         self._polling_task = self.loop.create_task(self._polling())
         self._dispatcher_task = self.loop.create_task(
             self.dispatcher.dispatch())
示例#5
0
 async def stop(self):
     log.info('stop bot')
     self.is_running = False
     await self.stop_polling()
     await self._session.close()
示例#6
0
    async def dispatch(self):
        while self.bot.is_running and self.bot.is_polling:
            task_len = len(asyncio.Task.all_tasks())
            if task_len < self.bot.task_max_len:
                # get event from queue
                event = await self.bot.events.get()

                # prepare user data
                user_id = event.data.get('from', {}).get('userId', None)
                if not user_id:
                    user_id = event.data.get('from', {}).get('chatId')

                user = self.bot.users.get(user_id, User(user_id, self.bot))
                self.bot.users[user_id] = user

                try:
                    log.info(f"dispatching event[{event.id}]")
                    processed = False
                    for handler in (h for h in self.handlers
                                    if h.check(event=event, dispatcher=self)):
                        log.info(
                            f'handle event[{event.id}] by handler[{handler}]')
                        if user.task and not user.task.done():
                            if isinstance(handler, DefaultHandler) or [
                                    i for i in handler.ignore
                                    if i is user.handler
                            ]:
                                log.info(
                                    f"handler[{handler}] was cancelled because user[{user}] have active task"
                                )
                                break
                            else:
                                try:
                                    log.info(
                                        f'attempt cancel user {user_id} task')
                                    user.handler = None
                                    user.task.cancel()
                                    await user.task
                                except Exception as e:
                                    log.info(e)
                        if handler.multiline:
                            user.task = self.bot.loop.create_task(
                                self.task_handler(handler, event, user))
                            user.parent_event_id = event.id
                            user.handler = handler
                        else:
                            log.info(f'create task for user[{user}]')
                            self.bot.loop.create_task(
                                handler.handle(event, self))
                        processed = True
                    if not processed and user.task and not user.task.done():
                        log.info(
                            f'put event[{event.id}] into user[{user_id}] queue'
                        )
                        await self.bot.users[user_id].events.put(event)
                except StopDispatching:
                    log.debug(
                        "Caught '{}' exception, stopping dispatching.".format(
                            StopDispatching.__name__))
                except Exception:
                    log.exception("Exception while dispatching event!")
            else:
                log.critical('task limit was reached: {}'.format(task_len))
                await asyncio.sleep(1)