v0.9.0
Highlights
set_busy_handler/3 and remove_busy_handler/1 are gone. The retry decision and the observation are now independent halves of one busy slot:
# retry decision (single slot — a policy cannot compose):
:ok = Xqlite.set_busy_policy(conn, max_retries: 50, max_elapsed_ms: 5_000, sleep_ms: 10)
:ok = Xqlite.remove_busy_policy(conn)
# observation (any number of subscribers, with or without a policy):
{:ok, handle} = Xqlite.register_busy_observer(conn, self())
# each contention callback delivers {:xqlite_busy, retries, elapsed_ms}busy_timeout/2 now clears the policy first. The raw PRAGMA busy_timeout still silently replaces the whole callback at the C level — documented, with the safe path spelled out.
The ergonomic surface is complete. Every raw introspection NIF now has a thin Xqlite wrapper: transaction-state readers (transaction_status/1, autocommit/1, txn_state/2), counters (last_insert_rowid/1, changes/1, total_changes/1, connection_stats/1), build info (compile_options/1, sqlite_version/0), and the full schema family through get_create_sql/2. Connection lifecycle joined earlier in the cycle: close/1 (idempotent), db_path/1, open_readonly/1, open_temporary/0. Hooks, sessions, and blob I/O remain deliberately raw XqliteNIF APIs.
OpenTelemetry vocabulary, zero dependencies. Xqlite.Telemetry.OpenTelemetry maps xqlite's telemetry events to the stable OTel database semantic conventions (db.system.name, db.query.text, db.operation.name, db.namespace, error.type) plus a span_name/2 suggestion. Every mapped name cites its spec page in the module docs.
Two new guides. Full-text search with FTS5 (external-content tables, triggers, bm25 ranking, highlight/snippet) and the doc-first Spatial data with SpatiaLite (per-platform install, gated extension loading, geometry columns, spatial index pattern — with honest caveats).
Telemetry promises kept. The [:xqlite, :open] span documented since 0.7.0 now actually fires on every open wrapper, close/1 emits its span, and busy observation re-emits through the bridge as [:xqlite, :hook, :busy].
Full details in the CHANGELOG.