diff --git a/client/app/pages/queries/query.html b/client/app/pages/queries/query.html index e4eff25bd2..f0050d0619 100644 --- a/client/app/pages/queries/query.html +++ b/client/app/pages/queries/query.html @@ -213,7 +213,7 @@

- Query in queue… + Query in queue (waiting on {{queryResult.job.queue_length}} queryies)… diff --git a/redash/tasks/queries.py b/redash/tasks/queries.py index abc967959b..8608c64101 100644 --- a/redash/tasks/queries.py +++ b/redash/tasks/queries.py @@ -181,12 +181,22 @@ def to_dict(self): else: query_result_id = None + queries_ahead = 0 + if task_status == 'PENDING': + waiting = QueryTaskTracker.all(QueryTaskTracker.WAITING_LIST) + waiting_length = len(waiting) + # find our job's index, return number of queries after it + for i, waiting_task in enumerate(waiting): + if waiting_task.data['task_id'] == self._async_result.id: + queries_ahead = waiting_length - i - 1 + break return { 'id': self._async_result.id, 'updated_at': updated_at, 'status': status, 'error': error, 'query_result_id': query_result_id, + 'queue_length': queries_ahead, } @property diff --git a/tests/handlers/test_query_results.py b/tests/handlers/test_query_results.py index 1af3c1a3a5..0f69254715 100644 --- a/tests/handlers/test_query_results.py +++ b/tests/handlers/test_query_results.py @@ -1,8 +1,9 @@ +import mock from tests import BaseTestCase from redash.models import db -from redash.utils import json_dumps - +from redash.tasks.queries import QueryTaskTracker +from redash.utils import gen_query_hash, json_dumps class TestQueryResultsCacheHeaders(BaseTestCase): def test_uses_cache_headers_for_specific_result(self): @@ -38,7 +39,6 @@ def test_get_existing_result(self): self.assertEquals(query_result.id, rv.json['query_result']['id']) def test_execute_new_query(self): - query_result = self.factory.create_query_result() query = self.factory.create_query() rv = self.make_request('post', '/api/query_results', @@ -50,6 +50,45 @@ def test_execute_new_query(self): self.assertNotIn('query_result', rv.json) self.assertIn('job', rv.json) + def test_queue_length(self): + query = self.factory.create_query() + tasks = [] + def fake_all(*a, **kw): + return tasks + def enqueue_query(query, *a, **kw): + from redash.tasks.queries import enqueue_query + job = enqueue_query(query, *a, **kw) + tasks.append(QueryTaskTracker.create( + task_id=job.id, + state='waiting', + query_hash=gen_query_hash(query), + data_source_id=None, + scheduled=False, + metadata={})) + return job + patch_all = mock.patch('redash.tasks.queries.QueryTaskTracker.all', + classmethod(fake_all)) + patch_enqueue_query = mock.patch('redash.handlers.query_results.enqueue_query', + enqueue_query) + with patch_all, patch_enqueue_query: + rv0 = self.make_request('post', '/api/query_results', + data={'data_source_id': self.factory.data_source.id, + 'query': query.query_text, + 'max_age': 0}) + rv1 = self.make_request('post', '/api/query_results', + data={'data_source_id': self.factory.data_source.id, + 'query': query.query_text, + 'max_age': 0}) + rv2 = self.make_request('post', '/api/query_results', + data={'data_source_id': self.factory.data_source.id, + 'query': query.query_text, + 'max_age': 0}) + + self.assertEquals(rv0.json['job']['queue_length'], 0) + self.assertEquals(rv1.json['job']['queue_length'], 1) + self.assertEquals(rv2.json['job']['queue_length'], 2) + + def test_execute_query_without_access(self): group = self.factory.create_group() db.session.commit()