mirror of
https://github.com/simonw/datasette.git
synced 2026-09-03 15:14:08 +02:00
Datasette has a family of callers that run a query under a tiny time limit and treat "did not finish" as a usable answer. table_counts() is the loudest: the homepage counts every table with a 10ms budget and stores None for the ones that blow it. The QueryInterrupted handler on the db.query span was unconditional, so on a two-table database that produced four ERROR spans - two db.query and two db.query.execute - on every homepage hit. Measured on a 30MB two-table database: 4 red spans before, 0 after. Honouring log_sql_errors here would have silenced none of it. Only the three ArrayFacet json_type() probes pass log_sql_errors=False, and they are not the queries that time out; table_counts() and ColumnFacet.suggest both leave it at its True default. The signal that does separate the two cases is the budget itself: a caller asking for less time than sql_time_limit_ms is saying the query may not finish. Keying off that needs no new API and no changes outside database.py. A query that runs out the instance-wide limit is still an error. datasette.interrupted is still set in every case - it is the signal worth having, and only the ERROR status becomes conditional. Its registry description said the status is "also set to ERROR" full stop, which is now wrong, and that string is published in docs/internals.rst. The inner db.query.execute span carried the same bug through set_status_on_exception=log_sql_errors, so its exception handling is now explicit, matching the db.query span above it. The context manager's flags apply to every exception type alike and this span has to tell two apart. test_query_interrupted_sets_error_status forced its timeout with ?_timelimit=5, which is exactly the signal now reclassified as expected. It now forces one via sql_time_limit_ms so it still tests what it was written to test. Also documents, at the copy_context() sites, that context propagation carries Datasette's non-OTel ContextVars into worker threads too. Verified harmless: nothing reads _skip_permission_checks, _permission_check_cache or _in_datasette_client off the event loop, and Context.run() restores the thread's previous context on return, so no value can reach the next task on the shared pool. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| _static | ||
| _templates | ||
| .gitignore | ||
| authentication.rst | ||
| auto-build.sh | ||
| binary_data.rst | ||
| changelog.rst | ||
| cli-reference.rst | ||
| codespell-ignore-words.txt | ||
| conf.py | ||
| configuration.rst | ||
| contributing.rst | ||
| csv_export.rst | ||
| custom_templates.rst | ||
| datasette-0.51.png | ||
| datasette-logo.svg | ||
| deploying.rst | ||
| ecosystem.rst | ||
| events.md | ||
| facets.rst | ||
| full_text_search.rst | ||
| getting_started.rst | ||
| index.rst | ||
| installation.rst | ||
| internals.rst | ||
| introspection.rst | ||
| javascript_plugins.rst | ||
| json_api.rst | ||
| json_api_doc.py | ||
| Makefile | ||
| metadata.rst | ||
| metadata_doc.py | ||
| pages.rst | ||
| performance.rst | ||
| plugin_hooks.rst | ||
| plugins.rst | ||
| publish.rst | ||
| settings.rst | ||
| spatialite.rst | ||
| sql_queries.rst | ||
| telemetry_doc.py | ||
| template_context.rst | ||
| template_context_doc.py | ||
| testing_plugins.rst | ||
| upgrade-1.0a20.md | ||
| upgrade_guide.md | ||
| writing_plugins.rst | ||