def record_errors(transaction, bug_watch_ids): """Context manager to record errors in BugWatchActivity. If an exception occurs, it will be logged in BugWatchActivity against all the given watches. """ try: yield except Exception as e: # We record the error against all the bugwatches that should # have been updated before re-raising it. We also update the # bug watches' lastchecked dates so that checkwatches # doesn't keep trying to update them every time it runs. with transaction: getUtility(IBugWatchSet).bulkSetError( bug_watch_ids, get_bugwatcherrortype_for_error(e)) raise
def _updateBugTracker(self, bug_tracker, batch_size=None): """Updates the given bug trackers's bug watches.""" with self.transaction: # Never work with more than 1000 bug watches at a # time. Especially after a release or an outage, a large # bug tracker could have have >10000 bug watches eligible # for update. bug_watches_to_update = ( bug_tracker.watches_needing_update.config(limit=1000)) bug_watches_need_updating = ( bug_watches_to_update.count() > 0) if bug_watches_need_updating: # XXX: GavinPanella 2010-01-18 bug=509223 : Ask remote # tracker which remote bugs have been modified, and use # this to fill up a batch, rather than figuring out # batching later in _getRemoteIdsToCheck(). try: trackers_and_watches = self._getExternalBugTrackersAndWatches( bug_tracker, bug_watches_to_update) except (UnknownBugTrackerTypeError, ProtocolError) as error: # We update all the bug watches to reflect the fact that # this error occurred. We also update their last checked # date to ensure that they don't get checked for another # 24 hours (see above). error_type = ( get_bugwatcherrortype_for_error(error)) with self.transaction: getUtility(IBugWatchSet).bulkSetError( bug_watches_to_update, error_type) self.logger.info( "'%s' error updating %s: %s" % ( error_type.title, bug_tracker.baseurl, error)) else: for remotesystem, bug_watch_batch in trackers_and_watches: self.updateBugWatches( remotesystem, bug_watch_batch, batch_size=batch_size) else: with self.transaction: self.logger.debug( "No watches to update on %s" % bug_tracker.baseurl)
def updateRemoteBug(self): with self.transaction: bug_watches = self._getBugWatchesForRemoteBug() # If there aren't any bug watches for this remote bug, # just log a warning and carry on. if len(bug_watches) == 0: self.warning( "Spurious remote bug ID: No watches found for " "remote bug %s on %s" % (self.remote_bug, self.external_bugtracker.baseurl) ) return # Mark them all as checked. for bug_watch in bug_watches: bug_watch.lastchecked = UTC_NOW bug_watch.next_check = None # Return if this one is definitely unmodified. if self.remote_bug in self.unmodified_remote_ids: return # Save the remote bug URL for error reporting. remote_bug_url = bug_watches[0].url # Save the list of local bug IDs for error reporting. local_ids = ", ".join(str(bug_id) for bug_id in sorted(watch.bug.id for watch in bug_watches)) try: new_remote_status = None new_malone_status = None new_remote_importance = None new_malone_importance = None error = None oops_id = None try: new_remote_status = self.external_bugtracker.getRemoteStatus(self.remote_bug) new_malone_status = self._convertRemoteStatus(new_remote_status) new_remote_importance = self.external_bugtracker.getRemoteImportance(self.remote_bug) new_malone_importance = self._convertRemoteImportance(new_remote_importance) except (InvalidBugId, BugNotFound, PrivateRemoteBug) as ex: error = get_bugwatcherrortype_for_error(ex) message = self.error_type_messages.get(error, self.error_type_message_default) self.logger.info( message % {"bug_id": self.remote_bug, "base_url": self.external_bugtracker.baseurl, "local_ids": local_ids} ) # Set the error and activity on all bug watches with self.transaction: getUtility(IBugWatchSet).bulkSetError(bug_watches, error) getUtility(IBugWatchSet).bulkAddActivity(bug_watches, result=error) else: # Assuming nothing's gone wrong, we can now deal with # each BugWatch in turn. for bug_watch in bug_watches: bug_watch_updater = BugWatchUpdater(self, bug_watch, self.external_bugtracker) bug_watch_updater.updateBugWatch( new_remote_status, new_malone_status, new_remote_importance, new_malone_importance ) except Exception as error: # Send the error to the log. oops_id = self.error( "Failure updating bug %r on %s (local bugs: %s)." % (self.remote_bug, self.bug_tracker_url, local_ids), properties=[("URL", remote_bug_url), ("bug_id", self.remote_bug), ("local_ids", local_ids)] + get_remote_system_oops_properties(self.external_bugtracker), ) # We record errors against the bug watches and update # their lastchecked dates so that we don't try to # re-check them every time checkwatches runs. error_type = get_bugwatcherrortype_for_error(error) with self.transaction: getUtility(IBugWatchSet).bulkSetError(bug_watches, error_type) getUtility(IBugWatchSet).bulkAddActivity(bug_watches, result=error_type, oops_id=oops_id)
def updateRemoteBug(self): with self.transaction: bug_watches = self._getBugWatchesForRemoteBug() # If there aren't any bug watches for this remote bug, # just log a warning and carry on. if len(bug_watches) == 0: self.warning( "Spurious remote bug ID: No watches found for " "remote bug %s on %s" % ( self.remote_bug, self.external_bugtracker.baseurl)) return # Mark them all as checked. for bug_watch in bug_watches: bug_watch.lastchecked = UTC_NOW bug_watch.next_check = None # Return if this one is definitely unmodified. if self.remote_bug in self.unmodified_remote_ids: return # Save the remote bug URL for error reporting. remote_bug_url = bug_watches[0].url # Save the list of local bug IDs for error reporting. local_ids = ", ".join( str(bug_id) for bug_id in sorted( watch.bug.id for watch in bug_watches)) try: new_remote_status = None new_malone_status = None new_remote_importance = None new_malone_importance = None error = None oops_id = None try: new_remote_status = ( self.external_bugtracker.getRemoteStatus( self.remote_bug)) new_malone_status = self._convertRemoteStatus( new_remote_status) new_remote_importance = ( self.external_bugtracker.getRemoteImportance( self.remote_bug)) new_malone_importance = self._convertRemoteImportance( new_remote_importance) except (InvalidBugId, BugNotFound, PrivateRemoteBug) as ex: error = get_bugwatcherrortype_for_error(ex) message = self.error_type_messages.get( error, self.error_type_message_default) self.logger.info( message % { 'bug_id': self.remote_bug, 'base_url': self.external_bugtracker.baseurl, 'local_ids': local_ids, }) # Set the error and activity on all bug watches with self.transaction: getUtility(IBugWatchSet).bulkSetError( bug_watches, error) getUtility(IBugWatchSet).bulkAddActivity( bug_watches, result=error) else: # Assuming nothing's gone wrong, we can now deal with # each BugWatch in turn. for bug_watch in bug_watches: bug_watch_updater = BugWatchUpdater( self, bug_watch, self.external_bugtracker) bug_watch_updater.updateBugWatch( new_remote_status, new_malone_status, new_remote_importance, new_malone_importance) except Exception as error: # Send the error to the log. oops_id = self.error( "Failure updating bug %r on %s (local bugs: %s)." % (self.remote_bug, self.bug_tracker_url, local_ids), properties=[ ('URL', remote_bug_url), ('bug_id', self.remote_bug), ('local_ids', local_ids)] + get_remote_system_oops_properties( self.external_bugtracker)) # We record errors against the bug watches and update # their lastchecked dates so that we don't try to # re-check them every time checkwatches runs. error_type = get_bugwatcherrortype_for_error(error) with self.transaction: getUtility(IBugWatchSet).bulkSetError( bug_watches, error_type) getUtility(IBugWatchSet).bulkAddActivity( bug_watches, result=error_type, oops_id=oops_id)