1. Marc-Alexandre Chan
  2. DailyPromptBot

Commits

Marc-Alexandre Chan  committed 43475c2

Events: fixed default value of interval not retrievable from config in ctor;
fixed missing database commits/closes

  • Participants
  • Parent commits b86f8ff
  • Branches dev-minibot

Comments (0)

Files changed (2)

File minibot/events.py

View file
  • Ignore whitespace
 
 """ Events and commands used by the Minibot event scheduler. """
 
-from minibot.errors import CommandError, CommandParseError, CommandNameError,\
-    CommandParameterError, MissingParameterError,\
-    APIException, BadCaptcha, ClientException, ExceptionList, InvalidUserPass,\
-    LoginRequired, ModeratorRequired, NonExistentUser, NotLoggedIn,\
-    RateLimitExceeded
+from minibot.errors import * # Bah!
 from minibot.db import Prompt, User, SuggestionThread
 from minibot.util import DateParseMixin, MarkdownMixin, DataFormatMixin,\
     classname, get_reddit_url
 from time     import strftime, localtime
 import re
 
+# TODO: Organise these events into files/modules
+
 # this is in all superscript (renders equiv. small text) ^(syntax is like this)
 _BOT_MSG = ("^(Having a problem with DailyPromptBot? Want to comment? You can "
 "contact [Laogeodritt](http://www.reddit.com/u/Laogeodritt) or leave us a note "
     Defaults:
         * ``start_time`` = 0
         * ``duration`` = -1
-        * ``interval`` = config.minibot.msg_rate (unless set before start())
+        * ``interval`` = 60
         * ``priority`` = 90
 
     """
     required_res = ['reddit', 'approved', 'config.minibot', 'logger']
     start_time = 0
     duration = -1
-    interval = None
+    interval = 60
     priority = 90
 
     def __init__(self):
         self.msg_chunk = self.res['config.minibot'].msg_chunk
         self.log = self.res['logger']
 
-        if self.interval is None:
-            self.interval = self.res['config.minibot'].msg_rate
-
         self.run() # start processing on first execution
 
     def run(self):
         (is a PM sent to the bot (not modmail) from an approved user). """
         return (msg.subreddit is None and
                 msg.dest == self.reddit.user.name and
-                msg.author.name in self.users)
+                msg.author.name.lower() in self.users)
 
     # command message parsing variables
     PARSE_FIELD = 0
         CommandParametersError (from the command constructor). """
         self.log.info('%s: message %s: building command: %s',
             classname(self), msg.id,
-            '; '.join(['='.join(x, y) for x, y in data.iteritems()]))
+            '; '.join(['='.join([x, y]) for x, y in data.iteritems()]))
         if data.has_key('action') and data['action'] in self.cmd_actions.keys():
             CommandClass = self.cmd_actions[data.pop('action')]
             cmd_obj = CommandClass(msg, **data)
     Defaults:
         * ``start_time`` = 0
         * ``duration`` = -1
-        * ``interval`` = config.minibot.queue_rate (unless set before start())
+        * ``interval`` = 60
         * ``priority`` = 80
 
     """
     required_res = ['dbsession', 'config.minibot', 'logger']
     start_time = 0
-    interval = None
+    interval = 60
     duration = -1
     priority = 80
 
     def start(self):
         self.log = self.res['logger']
 
-        if self.interval is None:
-            self.interval = self.res['config.minibot'].queue_rate
-
         self.run()
         return
 
                 id_, t_post.strftime("%Y-%m-%d %H:%M:%S UTC"))
                 new_cmd = PostPromptCommand(id_, t_post)
                 self.owner.queue_event(new_cmd)
+        self.db.close()
 
     def end(self):
-        pass
+        self.db.close()
 
     def handle_exception(self, e):
         if isinstance(e, SQLAlchemyError) or\
              isinstance(e, DBAPIError):
             self.res['dbsession'].rollback()
+            self.res['dbsession'].close()
             self.delay = 5
             return self.owner.EXC_HANDLED_RETRY
         return self.owner.EXC_UNHANDLED
     Defaults:
         * ``start_time`` = 0
         * ``duration`` = -1
-        * ``interval`` = config.minibot.queue_rate (unless set before start())
+        * ``interval`` = 60
         * ``priority`` = 75
 
     """
     required_res = ['dbsession', 'config.minibot', 'logger']
     start_time = 0
-    interval = None
+    interval = 60
     duration = -1
     priority = 75
 
     def start(self):
         self.log = self.res['logger']
 
-        if self.interval is None:
-            self.interval = self.res['config.minibot'].queue_rate
-
         self.run()
         return
 
                     id_, t_post.strftime("%Y-%m-%d %H:%M:%S UTC"))
                 new_cmd = PostSuggestionThreadCommand(id_, t_post)
                 self.owner.queue_event(new_cmd)
+        self.db.close()
+
+    def end(self):
+        self.db.close()
 
     def handle_exception(self, e):
         if isinstance(e, SQLAlchemyError) or\
              isinstance(e, DBAPIError):
             self.res['dbsession'].rollback()
+            self.res['dbsession'].close()
             self.delay = 5
             return self.owner.EXC_HANDLED_RETRY
         return self.owner.EXC_UNHANDLED
         else: # if a thread is found on that day, no action to take
             pass
 
+        db.close()
+
     def end(self):
-        pass
+        db.close()
 
     def handle_exception(self, e):
         self.res['dbsession'].rollback()
         if isinstance(e, SQLAlchemyError) or\
              isinstance(e, DBAPIError):
+            self.res['dbsession'].rollback()
+            self.res['dbsession'].close()
             self.delay = 5
             return self.owner.EXC_HANDLED_RETRY
         return self.owner.EXC_UNHANDLED
             classname(self), p['title'], new_prompt.id)
         self.log.debug("%s: %s", classname(self), repr(new_prompt))
 
+        db.close()
+
     def _run_reddit(self):
         self.msg.mark_as_read()
         self.log.debug("%s: Marked message %s as read.",
         * ``priority`` = 50
 
     """
-    required_res = ['reddit', 'dbsession', 'logger']
+    required_res = ['dbsession', 'logger']
     start_time = 0 # execute ASAP
     priority=50
 
         log.info("%s: Removed prompt '%s' (%d) from database queue.",
                  classname(self), self.prompt.title, self.prompt.id)
 
+        db.close()
+
     def _run_reddit(self):
         log = self.res['logger']
 
             "%s: Updated prompt '%s' (%d) in database queue.",
             classname(self), p['title'], prompt.id)
         self.log.debug("%s: %s", classname(self), repr(prompt))
+        db.close()
 
     def _run_reddit(self):
         prompt = self.prompt
         * ``priority`` = 60
 
     """
-    required_res = ['logger']
+    required_res = ['reddit', 'logger']
     start_time = 0 # execute ASAP
     priority = 60
 
             excerpt = self.text
         return "<{cls}: msgid={id_}, to={to}, title='{title}', message='{msg}'>".\
             format(cls=classname(self), id_=self.msg.id,
-            to=self.msg.author.name, msg=excerpt)
+            to=self.msg.author.name, title=self.title, msg=excerpt)
 
 
 class SendErrorMessageCommand(SendReplyCommand):
         self.msg.mark_as_read()
         self.log.debug("%s: Marked message %s as read.",
             classname(self), self.msg.name)
+        self.res['dbsession'].close()
 
     def _run_query(self):
         """ Return a Query object for the query configured. """
             return u'\n'.join(prompt_listing)
 
     def end(self):
-        pass
+        self.res['dbsession'].close()
+        del self.res['dbsession']
 
     def handle_exception(self, e):
         self.res['dbsession'].rollback()
         prompt.set_posted(r_sub.id)
         self.log.info("%s: Posted prompt %d to /r/%s", classname(self),
             prompt.id, target)
-        db.close()
+        db.commit()
 
     def end(self):
         self.res['dbsession'].close()
         self._add_link_to_last_thread()
         self.log.info("%s: Posted suggestion thread %d to /r/%s",
             classname(self), thread.id, target)
-        db.close()
+        db.commit()
 
     def end(self):
         self.res['dbsession'].close()

File minibot/eventscheduler.py

View file
  • Ignore whitespace
         while not self._exit_flag and not self._stop_flag and self._queue:
             # if not yet the next run time, sleep until then
             if time.time() < self._next_run:
-                time.sleep(self._next_run - time.time())
+                try:
+                    time.sleep(self._next_run - time.time())
+                except IOError: # signal interrupts sleep
+                    continue # then we want to reevaluate exit status
 
             # execute an iteration
             self._execute_iteration()
             event.end()
         elif status == self.STATUS_RUNNING:
             self.logger.debug("%s: Running event: %s",
-                classname(self), repr(self))
+                classname(self), repr(event))
             event.run()
         elif status == self.STATUS_ENDING:
             self.logger.info("%s: Terminating event: %s",
         elif res_name.startswith('config.') and\
                 hasattr(self._config, res_name[7:]):
             event.res[res_name] = getattr(self._config, res_name[7:])
-        elif (res_name == 'dbsession' and
-                ('dbsession' not in event.res.keys() or
-                    event.res['dbession'] is None)):
-            event.res['dbsession'] = self._db.get_new_session()
-            self.logger.debug('%s: Starting new database session for %s',
-                classname(self), repr(event))
+        elif res_name == 'dbsession':
+            # only set a new session if no existing session
+            if 'dbsession' not in event.res.keys() or\
+                    event.res['dbsession'] is None:
+                event.res['dbsession'] = self._db.get_new_session()
+                self.logger.debug('%s: Starting new database session for %s',
+                    classname(self), repr(event))
         elif res_name in self._res.keys():
             event.res[res_name] = self._res[res_name]
         else:
 
     def _set_timing(self, event):
         """ Set default event timing values if necessary. """
-        if not hasattr(event, 'start_time') or event.start_time < 0 or\
-                event.start_time is None:
+        if not hasattr(event, 'start_time') or event.start_time is None or\
+                event.start_time < 0:
             event.start_time = 0 # on next iteration
-        if not hasattr(event, 'interval') or event.interval < 0 or\
-                event.interval is None:
+        if not hasattr(event, 'interval') or event.interval is None or\
+                event.interval < 0:
             event.interval = 0 # single-run
-        if not hasattr(event, 'duration') or event.duration < -1 or\
-                event.duration is None:
+        if not hasattr(event, 'duration') or event.duration is None or\
+                event.duration < -1:
             event.duration = -1 # infinite run if interval is nonzero
         if not hasattr(event, 'priority') or event.priority is None:
             event.priority = 100