Ejegg has uploaded a new change for review. https://gerrit.wikimedia.org/r/197205
Change subject: Add execute_timeout to limit query lifespan ...................................................................... Add execute_timeout to limit query lifespan Brutally murders database connections after a set interval, raising an OperationalError on the calling thread. The Connection instance is useless afterward and should be re-instantiated. Change-Id: I0fca9533bb6c1e2bbf3cd88b4e298ac7e3d07335 --- M database/db.py 1 file changed, 27 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/wikimedia/fundraising/tools refs/changes/05/197205/1 diff --git a/database/db.py b/database/db.py index 4265627..4bed155 100644 --- a/database/db.py +++ b/database/db.py @@ -4,6 +4,7 @@ import MySQLdb as Dbi import atexit import os +import threading from signal import signal, SIGTERM, SIG_DFL from process.logging import Logger as log @@ -11,8 +12,10 @@ class Connection(object): def __init__(self, debug=False, **kw): + self.connectionArgs = kw self.db_conn = Dbi.connect(**kw) self.debug = debug + self.connection_id = None def close(self): self.db_conn.commit() @@ -37,6 +40,30 @@ out = cursor.fetchall() cursor.close() return out + + def execute_timeout(self, sql, params=None, timeout=0): + """ Execute a query with timeout. When a timeout occurs, kill the database connection """ + if timeout == 0: + return self.execute(sql, params) + + if self.connection_id == None: + self.connection_id = self.execute('SELECT CONNECTION_ID() AS cid')[0]['cid'] + + deathClock = threading.Timer(timeout, self.kill_connection) + deathClock.start() + + try: + return self.execute(sql, params) + finally: + deathClock.cancel() + + def kill_connection(self): + if self.debug: + log.debug('Killing connection {}'.format(self.connection_id)) + killerConnection = Dbi.connect(**self.connectionArgs) + cursor = killerConnection.cursor() + cursor.execute('KILL CONNECTION {}'.format(self.connection_id)) + killerConnection.close() def execute_paged(self, query, pageIndex, pageSize = 1000, dir = 'ASC'): """ Execute a paged query. This will yield a dictionary of the results @@ -117,7 +144,6 @@ for k, s in self.params.items(): qparams[k] = "'%s'" % s return self.uninterpolated_sql() % qparams - db_conn = dict() -- To view, visit https://gerrit.wikimedia.org/r/197205 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I0fca9533bb6c1e2bbf3cd88b4e298ac7e3d07335 Gerrit-PatchSet: 1 Gerrit-Project: wikimedia/fundraising/tools Gerrit-Branch: master Gerrit-Owner: Ejegg <eeggles...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits