mirror of
https://github.com/simonw/datasette.git
synced 2026-06-12 12:06:57 +02:00
Fix execute_isolated_fn() against immutable databases
execute_isolated_fn() always opened its temporary connection with write=True, which is not allowed for immutable databases - so APIs that rely on it, like SQL analysis when storing a query, failed. An immutable database can never receive writes, so there is no write queue to block: in that case the function now opens a read-only connection and runs it on the executor, bypassing the write thread entirely. Mutable databases keep the existing write-thread behavior. Also fixed a latent bug in the write thread where a connect() failure for an isolated task would crash the thread instead of delivering the exception back to the caller. Closes #2768 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6eaa9e3199
commit
d8605ef4c2
3 changed files with 94 additions and 19 deletions
|
|
@ -863,6 +863,39 @@ async def test_execute_isolated(db, disable_threads):
|
|||
assert not await db.execute_isolated_fn(table_exists_checker("created_by_isolated"))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_execute_isolated_connect_failure_does_not_kill_write_thread():
|
||||
# A connect() failure for an isolated task should be returned to the
|
||||
# caller as an exception, not crash the write thread
|
||||
class ConnectError(Exception):
|
||||
pass
|
||||
|
||||
ds = Datasette(memory=True)
|
||||
db = ds.add_memory_database("test_isolated_connect_failure")
|
||||
# Start the write thread with a healthy dedicated write connection
|
||||
await db.execute_write("create table dogs (id integer primary key)")
|
||||
|
||||
original_connect = db.connect
|
||||
|
||||
def broken_connect(write=False):
|
||||
raise ConnectError("Could not connect")
|
||||
|
||||
db.connect = broken_connect
|
||||
try:
|
||||
with pytest.raises(ConnectError):
|
||||
await asyncio.wait_for(db.execute_isolated_fn(lambda conn: None), timeout=2)
|
||||
finally:
|
||||
db.connect = original_connect
|
||||
|
||||
# Write thread should still be alive and processing tasks
|
||||
assert db._write_thread.is_alive()
|
||||
await db.execute_write("insert into dogs (id) values (1)")
|
||||
count = await db.execute_isolated_fn(
|
||||
lambda conn: conn.execute("select count(*) from dogs").fetchone()[0]
|
||||
)
|
||||
assert count == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_analyze_sql():
|
||||
ds = Datasette(memory=True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue