Show facets that timed out using new InterruptedError

If the user requests some _facet= options that do not successfully execute in
the configured facet_time_limit_ms, we now show a warning message like this:

    These facets timed out: rowid, Title

To build this I had to clean up our SQLite interrupted logic. We now raise a
custom InterruptedError exception when SQLite terminates due to exceeding a
time limit.

In implementing this I found and fixed a logic error where invalid SQL was
being generated in some cases for our faceting calculations but the resulting
sqlite3.OperationalError had been incorrectly captured and treated as a
timeout.

Refs #255
Closes #269
This commit is contained in:
Simon Willison 2018-05-17 23:07:45 -07:00
commit 08f4b7658f
No known key found for this signature in database
GPG key ID: 17E2DEA2588B7F52
4 changed files with 34 additions and 16 deletions

View file

@ -13,6 +13,7 @@ from sanic.views import HTTPMethodView
from datasette import __version__
from datasette.utils import (
CustomJSONEncoder,
InterruptedError,
InvalidSql,
path_from_row_pks,
path_with_added_args,
@ -170,7 +171,9 @@ class BaseView(RenderMixin):
else:
rows = cursor.fetchall()
truncated = False
except Exception as e:
except sqlite3.OperationalError as e:
if e.args == ('interrupted',):
raise InterruptedError(e)
print(
"ERROR: conn={}, sql = {}, params = {}: {}".format(
conn, repr(sql), params, e
@ -216,6 +219,8 @@ class BaseView(RenderMixin):
else:
data, extra_template_data, templates = response_or_template_contexts
except InterruptedError as e:
raise DatasetteError(str(e), title="SQL Interrupted", status=400)
except (sqlite3.OperationalError, InvalidSql) as e:
raise DatasetteError(str(e), title="Invalid SQL", status=400)