mirror of
https://github.com/simonw/datasette.git
synced 2026-10-20 16:26:58 +02:00
Schema watcher:
- Scan coalescing is loop-agnostic: in-flight scans are concurrent.futures
futures any event loop can wait for, taken over only when their loop has
closed or stopped; each refresh() resolves only its own scans. A write on
one loop no longer hangs forever when another loop's scan is in flight.
- At most one polling task across event loops; replaced pollers exit.
- A scan or catalog write that fails transiently (internal database locked,
shared-cache lock, cancellation) re-marks the database and retries it from
later requests and sweeps, with back-off; requests are never failed by it.
Write threads mark schema changes directly (under a lock) instead of
relying on a notification reaching a loop that may have closed.
- add_database() file databases and named in-memory databases use the
default_schema_watch mode (external unless configured). Named in-memory
databases can be external: polled with PRAGMA schema_version on their
write connection. They are not scanned at registration time, which raced
plugins filling them (datasette-copy-to-memory).
- close() no longer persists a fingerprint for an owned database whose file
header shows a schema the catalog has not seen.
- The derived-table permission rule (external-content FTS) trusts the
catalog only when a stat and header read prove it is current; otherwise
it asks the database, and schedules a rescan if the catalog is behind.
Connections and write threads:
- A BaseException from a write or isolated callback is delivered to the
caller as a RuntimeError instead of killing the thread silently.
- conn.close() on a write lease raises ConnectionLeaseError, and the write
thread reopens a connection something else closed.
- Write connections pin PRAGMA recursive_triggers=on (sqlite-utils FTS
triggers rely on it; idle reopen lost the old drift).
- execute_fn() accepts generators that no longer hold the connection or a
cursor.
- --crossdb _memory connections count against max_open_connections, are
reaped, and are discarded when databases are added or removed.
Lifecycle:
- The temp internal database file uses weakref.finalize, not atexit, so
closed or abandoned instances can be garbage collected.
- The read-pool reaper no longer keeps the last pool alive in its frame.
- The scratch directory is loaded (and locked) at the end of __init__, so a
failed construction leaves nothing locked.
- config_dir/scratch is used only if empty or created by Datasette; a second
instance on the same config dir starts without it; sidecar files are never
deleted the first time a directory is opened.
Regression tests: tests/test_connection_review_fixes.py (24 of 27 fail on
|
||
|---|---|---|
| .. | ||
| _static | ||
| _templates | ||
| images | ||
| shots | ||
| .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 | ||
| plugin_telemetry.rst | ||
| plugins.rst | ||
| publish.rst | ||
| settings.rst | ||
| settings_doc.py | ||
| shots.yml | ||
| 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 | ||