M1: ingest preflight — DuckDB lock detection, retry, and connection hygiene #508
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Batch ingests (
dev/scripts/ingest_opps.py, PFS ingest,aco.piperuns) failwith a raw
IOException: Could not set lock on file "data/aco.duckdb"whenever along-running reader (typically a marimo notebook kernel) holds a connection.
DuckDB is single-writer, so even a read-only handle blocks the writer.
Scope
on failure run
lsof data/aco.duckdb), then retry with backoff and, if stillheld, exit with an actionable message naming the holder PID/command
("marimo kernel — close the notebook tab or stop that PID").
conf.connectsocallers open→use→close instead of holding a connection for the process life.
connection alive across cells).
Background & alternatives:
docs/superpowers/specs/2026-07-08-duckdb-concurrency-streaming.md(option B).Implemented in
d809a45f92:conf.connect.duckdb_batch()— context-managed short-lived RW connection: retries the single-writer lock with exponential backoff, and on exhaustion raises naming the holder PIDs/commands vialsof("close the notebook tab or stop that PID") instead of the rawIOException. Always closes on exit.dev/scripts/ingest_opps.pyanddev/scripts/ingest_asp.py.docs/docs/duckdb-concurrency.md(read-only defaults in notebooks, no module-level connections, what to do when an ingest names a marimo PID).tests/conf/test_connect.py::TestDuckdbBatchincluding a real cross-process lock-holder case.The strategic fixes (per-domain split, read replica, lake) remain M2–M5: #510–#514.