Yuvipanda has uploaded a new change for review. https://gerrit.wikimedia.org/r/149657
Change subject: Add proper query killer ...................................................................... Add proper query killer Change-Id: I7b9c8e505c4992db088b25d0c8213d8e4290eec1 --- M quarry/web/app.py M quarry/web/models/queryresult.py M quarry/web/static/css/query/view.css M quarry/web/static/js/query/view.js M quarry/web/templates/query/view.html M tables.sql 6 files changed, 70 insertions(+), 23 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/analytics/quarry/web refs/changes/57/149657/1 diff --git a/quarry/web/app.py b/quarry/web/app.py index 23a994f..5f122d0 100644 --- a/quarry/web/app.py +++ b/quarry/web/app.py @@ -3,11 +3,12 @@ import pymysql from models.user import User from models.query import Query, QueryRevision, QueryRun -from models.queryresult import QuerySuccessResult, QueryErrorResult +from models.queryresult import QuerySuccessResult, QueryErrorResult, QueryKilledResult import json import time import os from celery import Celery +from celery.exceptions import SoftTimeLimitExceeded app = Flask(__name__) @@ -50,29 +51,52 @@ @celery.task -def run_query(query_run_id): - qrun = QueryRun.get_by_id(query_run_id) - qrun.status = QueryRun.STATUS_RUNNING - qrun.save() - start_time = time.clock() +def kill_query(thread_id): cur = g.replica.cursor() try: - cur.execute(qrun.query_rev.text) - total_time = time.clock() - start_time - result = [] - result.append(make_result(cur)) - while cur.nextset(): - result.append(make_result(cur)) - qresult = QuerySuccessResult(qrun, total_time, result, app.config['OUTPUT_PATH_TEMPLATE']) - qrun.status = QueryRun.STATUS_COMPLETE - except pymysql.DatabaseError as e: - total_time = time.clock() - start_time - qresult = QueryErrorResult(qrun, total_time, app.config['OUTPUT_PATH_TEMPLATE'], e.args[1]) - qrun.status = QueryRun.STATUS_FAILED + cur.execute("KILL QUERY %s", thread_id) + except pymysql.InternalError as e: + if e.args[0] == 1094: # Error code for 'no such thread' + print 'Query already killed' + else: + raise finally: cur.close() - qresult.output() - qrun.save() + + +@celery.task +def run_query(query_run_id): + qrun = QueryRun.get_by_id(query_run_id) + try: + qrun = QueryRun.get_by_id(query_run_id) + qrun.status = QueryRun.STATUS_RUNNING + qrun.save() + start_time = time.clock() + cur = g.replica.cursor() + try: + cur.execute(qrun.query_rev.text) + result = [] + result.append(make_result(cur)) + while cur.nextset(): + result.append(make_result(cur)) + total_time = time.clock() - start_time + qresult = QuerySuccessResult(qrun, total_time, result, app.config['OUTPUT_PATH_TEMPLATE']) + qrun.status = QueryRun.STATUS_COMPLETE + except pymysql.DatabaseError as e: + total_time = time.clock() - start_time + qresult = QueryErrorResult(qrun, total_time, app.config['OUTPUT_PATH_TEMPLATE'], e.args[1]) + qrun.status = QueryRun.STATUS_FAILED + finally: + cur.close() + qresult.output() + qrun.save() + except SoftTimeLimitExceeded: + total_time = time.clock() - start_time + kill_query.delay(g.replica.thread_id()) + qrun.state = QueryRun.STATUS_KILLED + qrun.save() + qresult = QueryKilledResult(qrun, total_time, app.config['OUTPUT_PATH_TEMPLATE']) + qresult.output() def get_user(): diff --git a/quarry/web/models/queryresult.py b/quarry/web/models/queryresult.py index 8016df2..6f9bf73 100644 --- a/quarry/web/models/queryresult.py +++ b/quarry/web/models/queryresult.py @@ -45,3 +45,14 @@ 'error': self.error } super(QueryErrorResult, self).output() + + +class QueryKilledResult(QueryResult): + def __init__(self, query_run, total_time, path_template): + super(QueryKilledResult, self).__init__(query_run, path_template, total_time) + + def output(self): + self.output_data = { + 'result': 'killed' + } + super(QueryKilledResult, self).output() diff --git a/quarry/web/static/css/query/view.css b/quarry/web/static/css/query/view.css index 56377f1..7c1b0b4 100644 --- a/quarry/web/static/css/query/view.css +++ b/quarry/web/static/css/query/view.css @@ -17,6 +17,6 @@ overflow-x: scroll; } -#query-result-success, #query-result-error, #query-progress { +#query-result-success, #query-result-error, #query-progress, #query-result-killed { display: none; } diff --git a/quarry/web/static/js/query/view.js b/quarry/web/static/js/query/view.js index 2d77f23..549dff2 100644 --- a/quarry/web/static/js/query/view.js +++ b/quarry/web/static/js/query/view.js @@ -58,12 +58,20 @@ $("#query-result-error").hide(); $("#query-result-success").show(); + $("#query-result-killed").hide(); } else if (d.result === 'error') { $("#error-time").text(d.time.toFixed(4) + "s"); $("#query-error-message").text(d.error); $("#query-progress").hide(); $("#query-result-error").show(); $("#query-result-success").hide(); + $("#query-result-killed").hide(); + } else if (d.result === 'killed' ) { + $("#killed-time").text(d.time.toFixed(4) + "s"); + $("#query-progress").hide(); + $("#query-result-error").hide(); + $("#query-result-success").hide(); + $("#query-result-killed").show(); } } ).fail( function() { setTimeout( checkOutput, 5000 ); diff --git a/quarry/web/templates/query/view.html b/quarry/web/templates/query/view.html index 953b7f8..49f7d14 100644 --- a/quarry/web/templates/query/view.html +++ b/quarry/web/templates/query/view.html @@ -33,9 +33,12 @@ </h3> </div> <div id="query-result-error"> - <h3>Error! <small id="error-time"></span></h3> + <h3>Error! <small id="error-time"></small></h3> <pre id="query-error-message"></pre> </div> + <div id="query-result-killed"> + <h3>Query killed! <small id="killed-time"></span></h3> + </div> <div id="query-progress"> <h3>Query running...</h3> </div> diff --git a/tables.sql b/tables.sql index 5a4fdcc..72f8041 100644 --- a/tables.sql +++ b/tables.sql @@ -8,7 +8,8 @@ user_id INT UNSIGNED NOT NULL, title VARCHAR(1024) BINARY NOT NULL, latest_rev INT UNSIGNED, - last_touched TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + last_touched TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + parent_id INT UNSIGNED ); CREATE TABLE query_revision( -- To view, visit https://gerrit.wikimedia.org/r/149657 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7b9c8e505c4992db088b25d0c8213d8e4290eec1 Gerrit-PatchSet: 1 Gerrit-Project: analytics/quarry/web Gerrit-Branch: master Gerrit-Owner: Yuvipanda <yuvipa...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits