Commits

Marc-Alexandre Chan committed 87ce91b

Fixed lack of error handling during scheduler exit routine. Fixes issue 2.

Comments (0)

Files changed (2)

     not in the Scheduler's queue. Argument is the event itself. """
     pass
 
+class SchedulerStoppedError(MinibotError):
+    """ Raised if an event is queued while the scheduler is in shutdown mode
+    (``request_exit()`` was called). """
+    pass
+
 # EVENTS
 class CommandError(MinibotError):
     """ Abstract base class for Command errors. """

minibot/eventscheduler.py

 from minibot.util import classname, log_exc_info
 from minibot.errors import ResourceError, AttachedEventError, InvalidUserPass,\
     LoginRequired, NotLoggedIn, RateLimitExceeded, EventNotFoundError,\
-    HTTPError
+    HTTPError, MinibotError
 
 from praw import Reddit
 
         self.logger.info("%s: Exiting the event scheduler.", classname(self))
         self.logger.info("%s: Stopping all events.", classname(self))
         while self._queue:
-            evtime, evpriority, evstatus, event = self._queue.pop(0)
+            evtime, evprio, evstatus, event = self._queue.pop(0)
             if evstatus == self.STATUS_RUNNING or\
                evstatus == self.STATUS_ENDING:
                 self.logger.debug("%s: Stopping event: %s",
                                   classname(self), repr(event))
-                event.end() # allow it to do cleanup
+                try:
+                    event.end() # allow it to do cleanup
+                except Exception as e:
+                    self._handle_exception(evtime, evprio, evstatus, event, e)
                 del event
             elif evstatus == self.STATUS_QUEUED or\
                  evstatus == self.STATUS_ONESHOT:
             status = self.STATUS_ONESHOT
         else:
             status = self.STATUS_QUEUED
+
         self._insert_event(event.start_time, event.priority, status, event)
         self.logger.info(
             "%s: Queued event: time=%s, priority=%d, status=%s, event=%s",
 
     def _insert_event(self, evtime, priority, status, event):
         """ Insert an event into the appropriate location in a queue. """
+        if self._exit_flag:
+            raise SchedulerStoppedError()
+
         evtuple = (evtime, priority, status, event)
         insert_at = len(self._queue) # insert at end by default
         for q_i, q_evtuple in enumerate(self._queue):
                 r_status = self.STATUS_ENDING
                 r_time   = end_time
 
-            self._insert_event(r_time, r_priority, r_status, event)
-            self.logger.debug(
-                "%s: Requeued event: time=%s, priority=%d, status=%s, event=%s",
-                classname(self),
-                time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(r_time)),
-                r_priority, self.STATUS_STRING[r_status], repr(event))
+            try:
+                self._insert_event(r_time, r_priority, r_status, event)
+            except SchedulerStoppedError:
+                self.logger.debug( # debug since called in exc handling
+                    "%s: Cannot requeue event during shutdown: "
+                    "time=%s, priority=%d, status=%s, event=%s",
+                    classname(self),
+                    time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(r_time)),
+                    r_priority, self.STATUS_STRING[r_status], repr(event))
+            else:
+                self.logger.debug(
+                    "%s: Requeued event: "
+                    "time=%s, priority=%d, status=%s, event=%s",
+                    classname(self),
+                    time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(r_time)),
+                    r_priority, self.STATUS_STRING[r_status], repr(event))
 
         # STATUS_ENDING or STATUS_ONESHOT have now ended and cleaned up
         # so nothing to do there
         """
         self.prepare_event(event)
         r_time = self._next_run + event.delay
-        self._insert_event(r_time, priority, status, event)
+        try:
+            self._insert_event(r_time, priority, status, event)
+        except SchedulerStoppedError:
+            self.logger.debug( # debug since called in exc handling
+                "%s: Cannot queue retry during shutdown: "
+                "time=%s, priority=%d, status=%s, event=%s",
+                classname(self),
+                time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(r_time)),
+                r_priority, self.STATUS_STRING[r_status], repr(event))
+        else:
+            self.logger.debug(
+                "%s: Queued retry: "
+                "time=%s, priority=%d, status=%s, event=%s",
+                classname(self),
+                time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(r_time)),
+                r_priority, self.STATUS_STRING[r_status], repr(event))
         event.delay = None
 
     def prepare_event(self, event):