From f8a8185eb0044b5e3f5640bde4c9e9e49ec69f71 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sun, 12 Feb 2012 11:24:06 +0200 Subject: [PATCH 1/2] Attempt to catch the OperationalError which is thrown when MySQL closes the connection without telling us. --- openlp/core/lib/db.py | 81 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 2e7757324..69af22916 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -239,6 +239,16 @@ class Manager(object): 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 + 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') @@ -260,6 +270,16 @@ class Manager(object): 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 + 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') @@ -278,7 +298,14 @@ class Manager(object): if not key: return object_class() else: - return self.session.query(object_class).get(key) + 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 + self.session.rollback() + return self.session.query(object_class).get(key) def get_object_filtered(self, object_class, filter_clause): """ @@ -290,7 +317,14 @@ class Manager(object): ``filter_clause`` The criteria to select the object by """ - return self.session.query(object_class).filter(filter_clause).first() + 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 + self.session.rollback() + return self.session.query(object_class).filter(filter_clause).first() def get_all_objects(self, object_class, filter_clause=None, order_by_ref=None): @@ -311,10 +345,17 @@ class Manager(object): if filter_clause is not None: query = query.filter(filter_clause) if isinstance(order_by_ref, list): - return query.order_by(*order_by_ref).all() + query = query.order_by(*order_by_ref) elif order_by_ref is not None: - return query.order_by(order_by_ref).all() - return query.all() + 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 + self.session.rollback() + return query.all() def get_object_count(self, object_class, filter_clause=None): """ @@ -330,7 +371,14 @@ class Manager(object): query = self.session.query(object_class) if filter_clause is not None: query = query.filter(filter_clause) - return query.count() + 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 + self.session.rollback() + return query.count() def delete_object(self, object_class, key): """ @@ -349,6 +397,15 @@ class Manager(object): 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 + 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') @@ -378,6 +435,18 @@ class Manager(object): 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 + 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__) From bcad2c171f08b99de95c67581ab8e6710d99aff2 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 16 Feb 2012 21:05:16 +0200 Subject: [PATCH 2/2] Added exception logging in case we need to confirm that we are actually getting the exception we think we are. --- openlp/core/lib/db.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 69af22916..d7ca10f0f 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -243,6 +243,7 @@ class Manager(object): # 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: @@ -274,6 +275,7 @@ class Manager(object): # 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: @@ -304,6 +306,7 @@ class Manager(object): # 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) @@ -323,6 +326,7 @@ class Manager(object): # 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() @@ -354,6 +358,7 @@ class Manager(object): # 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() @@ -377,6 +382,7 @@ class Manager(object): # 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() @@ -401,6 +407,7 @@ class Manager(object): # 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() @@ -439,6 +446,7 @@ class Manager(object): # 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: