diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index d7687c56f..28d6f8b92 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -239,27 +239,30 @@ class Manager(object): ``commit`` Commit the session with this object """ - try: - self.session.add(object_instance) - if commit: - self.session.commit() - self.is_dirty = True - return True - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue - "MySQL has gone away"') - self.session.rollback() - self.session.add(object_instance) - if commit: - self.session.commit() - self.is_dirty = True - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Object save failed') - return False + for try_count in range(3): + try: + self.session.add(object_instance) + if commit: + self.session.commit() + self.is_dirty = True + return True + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue - "MySQL has gone away"') + self.session.rollback() + if try_count >= 2: + raise + except InvalidRequestError: + self.session.rollback() + log.exception(u'Object list save failed') + return False + except: + self.session.rollback() + raise def save_objects(self, object_list, commit=True): """ @@ -271,27 +274,30 @@ class Manager(object): ``commit`` Commit the session with this object """ - try: - self.session.add_all(object_list) - if commit: - self.session.commit() - self.is_dirty = True - return True - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - self.session.add_all(object_list) - if commit: - self.session.commit() - self.is_dirty = True - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Object list save failed') - return False + for try_count in range(3): + try: + self.session.add_all(object_list) + if commit: + self.session.commit() + self.is_dirty = True + return True + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + self.session.rollback() + if try_count >= 2: + raise + except InvalidRequestError: + self.session.rollback() + log.exception(u'Object list save failed') + return False + except: + self.session.rollback() + raise def get_object(self, object_class, key=None): """ @@ -306,15 +312,18 @@ class Manager(object): if not key: return object_class() else: - try: - return self.session.query(object_class).get(key) - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - return self.session.query(object_class).get(key) + for try_count in range(3): + try: + return self.session.query(object_class).get(key) + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + if try_count >= 2: + raise def get_object_filtered(self, object_class, filter_clause): """ @@ -326,15 +335,18 @@ class Manager(object): ``filter_clause`` The criteria to select the object by """ - try: - return self.session.query(object_class).filter(filter_clause).first() - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - return self.session.query(object_class).filter(filter_clause).first() + for try_count in range(3): + try: + return self.session.query(object_class).filter(filter_clause).first() + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + if try_count >= 2: + raise def get_all_objects(self, object_class, filter_clause=None, order_by_ref=None): @@ -358,15 +370,18 @@ class Manager(object): query = query.order_by(*order_by_ref) elif order_by_ref is not None: query = query.order_by(order_by_ref) - try: - return query.all() - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - return query.all() + for try_count in range(3): + try: + return query.all() + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + if try_count >= 2: + raise def get_object_count(self, object_class, filter_clause=None): """ @@ -382,15 +397,18 @@ class Manager(object): query = self.session.query(object_class) if filter_clause is not None: query = query.filter(filter_clause) - try: - return query.count() - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - return query.count() + for try_count in range(3): + try: + return query.count() + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + if try_count >= 2: + raise def delete_object(self, object_class, key): """ @@ -404,25 +422,29 @@ class Manager(object): """ if key != 0: object_instance = self.get_object(object_class, key) - try: - self.session.delete(object_instance) - self.session.commit() - self.is_dirty = True - return True - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - self.session.delete(object_instance) - self.session.commit() - self.is_dirty = True - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Failed to delete object') - return False + for try_count in range(3): + try: + self.session.delete(object_instance) + self.session.commit() + self.is_dirty = True + return True + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + self.session.rollback() + if try_count >= 2: + raise + except InvalidRequestError: + self.session.rollback() + log.exception(u'Failed to delete object') + return False + except: + self.session.rollback() + raise else: return True @@ -440,31 +462,32 @@ class Manager(object): The filter governing selection of objects to return. Defaults to None. """ - try: - query = self.session.query(object_class) - if filter_clause is not None: - query = query.filter(filter_clause) - query.delete(synchronize_session=False) - self.session.commit() - self.is_dirty = True - return True - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - query = self.session.query(object_class) - if filter_clause is not None: - query = query.filter(filter_clause) - query.delete(synchronize_session=False) - self.session.commit() - self.is_dirty = True - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Failed to delete %s records', object_class.__name__) - return False + for try_count in range(3): + try: + query = self.session.query(object_class) + if filter_clause is not None: + query = query.filter(filter_clause) + query.delete(synchronize_session=False) + self.session.commit() + self.is_dirty = True + return True + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + self.session.rollback() + if try_count >= 2: + raise + except InvalidRequestError: + self.session.rollback() + log.exception(u'Failed to delete %s records', object_class.__name__) + return False + except: + self.session.rollback() + raise def finalise(self): """