Revision history for DBIO-Async
0.900001 2026-07-12
First release. The shared, loop-agnostic async layer for DBIO drivers.
* Storage
- DBIO::Async::Storage, the future_io transport backend subclassing
core DBIO::Storage::Async: it inherits the Model-B orchestration
(_run_crud / txn_do_async / pipeline, sync ->get fallbacks,
connect-info normalisation, AccessBroker wiring) from core (ADR
0030 §4) and supplies only the transport -- Future::IO query
execution (_query_async / _query_async_pinned over an isolated
watcher seam: _await_conn_ready / _await_query_result over
ready_for_read on a driver-supplied socket fd), the Future class,
and the connection pool. DB-specific seam hooks croak "Subclass
must override" until a driver overrides them.
- future_io resolves a driver's DBIO::Async::Storage subclass by
CONVENTION in core (ref($storage) . '::Async'); loading DBIO::Async
no longer globally registers future_io on the core base
(ADR 0030 refinement, karr #65).
- _query_async / _query_async_pinned shape sql_maker's '?' placeholders
into the driver dialect internally via the inherited _transform_sql
seam (core #70 WP3, karr #3); the shaping is idempotent on
already-shaped SQL (including a '?' inside a quoted literal), so it
is safe alongside core's own call-site shaping during the
transition. Declares transport_capabilities => ('on_connect_replay'),
so an async layer that needs on_connect replay (e.g. AGE) can compose
onto this transport instead of silently losing the capability
(backed by the pool -> _setup_pool_connection -> _run_pool_connect_statement
replay chain, karr #68).
- The poll fd a driver's _conn_fileno returns is wrapped once per
connection into a cached filehandle (_conn_poll_fh, dup'd via
open '+<&') for Future::IO->poll, and reused by _await_readable.
Some Future::IO impls (e.g. IO::Async) mark a future done, and thus
run its on_ready close, BEFORE unwatch_io's by fileno; dup-and-close
per poll left a closed handle whose fileno came back undef and
corrupted the impl's watch table. One stable handle per connection
keeps the fileno valid across the whole watch/unwatch cycle. This
establishes a documented base assumption: $conn is a hashref, with
the poll filehandle cached under a reserved key. karr #25.
* Pool
- DBIO::Async::Pool subclassing core DBIO::Storage::PoolBase with a
generalized connection-readiness role: drivers whose connection
object is not immediately ready supply it; others short-circuit
to done($conn).
* TransactionContext
- DBIO::Async::TransactionContext, a thin subclass of core's generic
DBIO::Storage::Async::TransactionContext (ADR 0030 §4): the unified
txn_conn accessor / pinned-connection wrapper -- replacing the
per-driver txn_pg / txn_mdb names -- now lives in core and is
inherited unchanged.
* Dependencies
- The Future / Future::IO requirements live here, not in each
driver, so a sync-only driver pulls no async dependencies —
installing dbio-async is what turns async on. Future::IO's
built-in default impl is IO::Poll; no event loop is a hard
require (core ADR 0014).