parameters: (self, activity_tool, message_list,
                                 uid_to_duplicate_uid_list_dict=None)
docstring: If everything was fine, delete all messages.
        If anything failed, make successful messages available (if any), and
        the following rules apply to failed messages:
          - Failures due to ConflictErrors cause messages to be postponed,
            but their retry count is *not* increased.
          - Failures of messages already above maximum retry count cause them to
            be put in a permanent-error state.
          - In all other cases, retry count is increased and message is delayed.
docstring_summary: If everything was fine, delete all messages.
        If anything failed, make successful messages available (if any), and
        the following rules apply to failed messages:
          - Failures due to ConflictErrors cause messages to be postponed,
            but their retry count is *not* increased.
          - Failures of messages already above maximum retry count cause them to
            be put in a permanent-error state.
          - In all other cases, retry count is increased and message is delayed.
docstring_tokens: If everything was fine delete all messages . If anything failed make successful messages available ( if any ) and the following rules apply to failed messages : - Failures due to ConflictErrors cause messages to be postponed but their retry count is * not * increased . - Failures of messages already above maximum retry count cause them to be put in a permanent - error state . - In all other cases retry count is increased and message is delayed .
function: def finalizeMessageExecution(self, activity_tool, message_list,
                                 uid_to_duplicate_uid_list_dict=None):
      """
        If everything was fine, delete all messages.
        If anything failed, make successful messages available (if any), and
        the following rules apply to failed messages:
          - Failures due to ConflictErrors cause messages to be postponed,
            but their retry count is *not* increased.
          - Failures of messages already above maximum retry count cause them to
            be put in a permanent-error state.
          - In all other cases, retry count is increased and message is delayed.
      """
      db = activity_tool.getSQLConnection()
      deletable_uid_list = []
      delay_uid_list = []
      final_error_uid_list = []
      make_available_uid_list = []
      notify_user_list = []
      executed_uid_list = deletable_uid_list
      if uid_to_duplicate_uid_list_dict is not None:
        for m in message_list:
          if m.getExecutionState() == MESSAGE_NOT_EXECUTED:
            executed_uid_list = make_available_uid_list
            break
      for m in message_list:
        uid = m.uid
        if m.getExecutionState() == MESSAGE_EXECUTED:
          executed_uid_list.append(uid)
          if uid_to_duplicate_uid_list_dict is not None:
            executed_uid_list += uid_to_duplicate_uid_list_dict.get(uid, ())
        elif m.getExecutionState() == MESSAGE_NOT_EXECUTED:
          # Should duplicate messages follow strictly the original message, or
          # should they be just made available again ?
          if uid_to_duplicate_uid_list_dict is not None:
            make_available_uid_list += uid_to_duplicate_uid_list_dict.get(uid, ())
          if (m.exc_type and # m.exc_type may be None
              (m.conflict_retry if issubclass(m.exc_type, ConflictError) else
               m.exc_type is SkippedMessage)):
            delay_uid_list.append(uid)
          else:
            max_retry = m.max_retry
            retry = m.line.retry
            if (max_retry is not None and retry >= max_retry) or \
                m.exc_type == TimeoutReachedError:
              # Always notify when we stop retrying.
              notify_user_list.append((m, False))
              final_error_uid_list.append(uid)
              continue
            # In case of infinite retry, notify the user
            # when the default limit is reached.
            if max_retry is None and retry == DEFAULT_MAX_RETRY:
              notify_user_list.append((m, True))
            delay = m.delay
            if delay is None:
              # By default, make delay quadratic to the number of retries.
              delay = VALIDATION_ERROR_DELAY * (retry * retry + 1) * 2
            try:
              # Immediately update, because values different for every message
              self.reactivateMessageList(db, (uid,), delay, True)
            except:
              self._log(WARNING, 'Failed to reactivate %r' % uid)
          make_available_uid_list.append(uid)
        else: # MESSAGE_NOT_EXECUTABLE
          # 'path' does not point to any object. Activities are normally flushed
          # (without invoking them) when an object is deleted, but this is only
          # an optimisation. There is no efficient and reliable way to do such
          # this, because a concurrent and very long transaction may be about to
          # activate this object, without conflict.
          # So we have to clean up any remaining activity.
          deletable_uid_list.append(uid)
      if deletable_uid_list:
        try:
          self._retryOnLockError(self.deleteMessageList, (db, deletable_uid_list))
        except:
          self._log(ERROR, 'Failed to delete messages %r' % deletable_uid_list)
        else:
          self._log(TRACE, 'Deleted messages %r' % deletable_uid_list)
      if delay_uid_list:
        try:
          # If this is a conflict error, do not increase 'retry' but only delay.
          self.reactivateMessageList(db, delay_uid_list,
                                     VALIDATION_ERROR_DELAY, False)
        except:
          self._log(ERROR, 'Failed to delay %r' % delay_uid_list)
      if final_error_uid_list:
        try:
          self.assignMessageList(db, INVOKE_ERROR_STATE, final_error_uid_list)
        except:
          self._log(ERROR, 'Failed to set message to error state for %r'
                           % final_error_uid_list)
      if make_available_uid_list:
        try:
          self.assignMessageList(db, 0, make_available_uid_list)
        except:
          self._log(ERROR, 'Failed to unreserve %r' % make_available_uid_list)
        else:
          self._log(TRACE, 'Freed messages %r' % make_available_uid_list)
      try:
        for m, retry in notify_user_list:
          m.notifyUser(activity_tool, retry)
      except:
        # Notification failures must not cause this method to raise.
        self._log(WARNING,
          'Exception during notification phase of finalizeMessageExecution')
function_tokens: def finalizeMessageExecution ( self , activity_tool , message_list , uid_to_duplicate_uid_list_dict = None ) : db = activity_tool . getSQLConnection ( ) deletable_uid_list = [ ] delay_uid_list = [ ] final_error_uid_list = [ ] make_available_uid_list = [ ] notify_user_list = [ ] executed_uid_list = deletable_uid_list if uid_to_duplicate_uid_list_dict is not None : for m in message_list : if m . getExecutionState ( ) == MESSAGE_NOT_EXECUTED : executed_uid_list = make_available_uid_list break for m in message_list : uid = m . uid if m . getExecutionState ( ) == MESSAGE_EXECUTED : executed_uid_list . append ( uid ) if uid_to_duplicate_uid_list_dict is not None : executed_uid_list += uid_to_duplicate_uid_list_dict . get ( uid , ( ) ) elif m . getExecutionState ( ) == MESSAGE_NOT_EXECUTED : # Should duplicate messages follow strictly the original message, or # should they be just made available again ? if uid_to_duplicate_uid_list_dict is not None : make_available_uid_list += uid_to_duplicate_uid_list_dict . get ( uid , ( ) ) if ( m . exc_type and # m.exc_type may be None ( m . conflict_retry if issubclass ( m . exc_type , ConflictError ) else m . exc_type is SkippedMessage ) ) : delay_uid_list . append ( uid ) else : max_retry = m . max_retry retry = m . line . retry if ( max_retry is not None and retry >= max_retry ) or m . exc_type == TimeoutReachedError : # Always notify when we stop retrying. notify_user_list . append ( ( m , False ) ) final_error_uid_list . append ( uid ) continue # In case of infinite retry, notify the user # when the default limit is reached. if max_retry is None and retry == DEFAULT_MAX_RETRY : notify_user_list . append ( ( m , True ) ) delay = m . delay if delay is None : # By default, make delay quadratic to the number of retries. delay = VALIDATION_ERROR_DELAY * ( retry * retry + 1 ) * 2 try : # Immediately update, because values different for every message self . reactivateMessageList ( db , ( uid , ) , delay , True ) except : self . _log ( WARNING , 'Failed to reactivate %r' % uid ) make_available_uid_list . append ( uid ) else : # MESSAGE_NOT_EXECUTABLE # 'path' does not point to any object. Activities are normally flushed # (without invoking them) when an object is deleted, but this is only # an optimisation. There is no efficient and reliable way to do such # this, because a concurrent and very long transaction may be about to # activate this object, without conflict. # So we have to clean up any remaining activity. deletable_uid_list . append ( uid ) if deletable_uid_list : try : self . _retryOnLockError ( self . deleteMessageList , ( db , deletable_uid_list ) ) except : self . _log ( ERROR , 'Failed to delete messages %r' % deletable_uid_list ) else : self . _log ( TRACE , 'Deleted messages %r' % deletable_uid_list ) if delay_uid_list : try : # If this is a conflict error, do not increase 'retry' but only delay. self . reactivateMessageList ( db , delay_uid_list , VALIDATION_ERROR_DELAY , False ) except : self . _log ( ERROR , 'Failed to delay %r' % delay_uid_list ) if final_error_uid_list : try : self . assignMessageList ( db , INVOKE_ERROR_STATE , final_error_uid_list ) except : self . _log ( ERROR , 'Failed to set message to error state for %r' % final_error_uid_list ) if make_available_uid_list : try : self . assignMessageList ( db , 0 , make_available_uid_list ) except : self . _log ( ERROR , 'Failed to unreserve %r' % make_available_uid_list ) else : self . _log ( TRACE , 'Freed messages %r' % make_available_uid_list ) try : for m , retry in notify_user_list : m . notifyUser ( activity_tool , retry ) except : # Notification failures must not cause this method to raise. self . _log ( WARNING , 'Exception during notification phase of finalizeMessageExecution' )