Changes for version 0.900001 - 2026-07-12
- Storage
- DBIO::MySQL::EV::Storage becomes a thin transport over the shared core Model-B machinery (720 -> 623 lines, ~208 code lines / 22 subs): select_async/…/delete_async, _run_crud, txn_do_async, the sync fallbacks, _generate_sql, sql_maker, new, schema/debug/ connected/disconnect/DESTROY, pipeline and the prepared-statement cache are all deleted and now inherited from core DBIO::Storage::Async (coderef-identity asserted in tests). What's kept is genuine MySQL value-add: _transform_sql as identity (MySQL speaks '?' natively, no ?->$N rewrite; applied first in the query seams to keep the core '?'-seam contract uniform), insert_async/_run_crud_pinned(insert) (no RETURNING, so INSERT + SELECT LAST_INSERT_ID() ride the same pinned session and the LII folds onto the auto-increment column), and _normalize_async_connect_info (dbname -> database). pool() now passes storage => $self so core's _setup_pool_connection fires on_connect_do/on_connect_call replay for every spawned EV pool connection (_run_pool_connect_statement drives it synchronously on the EV::MariaDB handle). transport_capabilities is (on_connect_replay) only -- no LISTEN/NOTIFY/COPY; pipeline is not claimed as a capability (EV::MariaDB pipelines automatically at the wire with no explicit-mode API to map onto the base seams). karr #18, #19, core #70.
- Bugfixes
- AccessBroker::Credentials was removed from core (split into ::Static for single-identity and DBIO::Replicated for routing); a stale local copy had masked the break, so a fresh install/smoker hit "Can't locate DBIO/AccessBroker/Credentials.pm". Switched the test to ::Static, mirroring the dbio-postgresql fix. karr #10.
- The async path retained bind values on the in-flight bind arrayref after a query's Future completed (the sync path clears them once execute() returns), causing a re-issued query on the same handle to see stale binds while a prior future was pending, and memory growth proportional to total binds ever issued rather than outstanding queries. Bind values are now cleared in the completion handler (fires on both done and fail), never on the issuing side (which would corrupt a still-pending query's binds). Per CurtisPoe architecture review #5, karr #11.
- Three driver bugs surfaced by the first end-to-end test driving the real DBIO facade through EV::MariaDB + EV::run (the mock-based suite only ever proved the Future API shape, never that the driver works against a live DB): Storage.pm's pool() was missing a lazy require for QueryExecutor (fired "Can't locate object method 'new'" on first use); txn_do_async held its coderef Future only weakly via a bare ->then->catch chain, so it could be GC'd before BEGIN's callback fired, silently hanging any EV::run-based wait loop -- fixed with ->retain, mirroring the dbio-postgresql-async fix; and QueryExecutor's execute() passed a bind arrayref to $mdb->query, which silently ignores it, so bound queries either threw a syntax error or ran with stale binds from the previous prepared statement -- now routed through prepare+execute whenever binds are non-empty. txn_do_async's on_fail also now surfaces a ROLLBACK failure as a wrapped error instead of dropping it silently.
- Fix PRODUCTION BUG: the first bound async query on a cold pool connection died 'not connected' (karr #20). DBIO::MySQL::EV::Pool wired on_connect => sub {} -- a pure no-op -- so it never tracked connection readiness; core DBIO::Storage::PoolBase's connection-readiness gate (karr #75) had nothing to wait on. _create_connection now registers a real per-connection readiness Future (core _register_connection_ready) resolved from EV::MariaDB's on_connect/on_error, and a new _connection_ready_future override looks it up -- mirroring dbio-postgresql-ev's karr #9 fix. New offline regression test t/08-pool-readiness.t (mirrors PG's t/04). Closes karr #19's leftover gap.
- Async opt-in via { async => 'ev' } (ADR 0030, karr #14)
- Dropped the connection()/storage_type hijack in DBIO::MySQL::EV. Loading the MySQL::EV component is now an inert marker; the EV backend is reached explicitly through MyApp::Schema->connect($dsn, $u, $p, { async => 'ev' }), which resolves the 'ev' mode via DBIO::MySQL::Storage's mode registry (the registration is its own karr ticket on the dbio-mysql board). PostgreSQL's DBIO::PostgreSQL::EV has no such override either; this brings MySQL to parity.
- insert_async resolves with the returned-columns HASHREF (ADR 0031 §3)
- MySQL has no RETURNING clause; the EV storage reads SELECT LAST_INSERT_ID() on the pinned connection and assembles the hashref = { %to_insert, $col => $lii_id } via the new _insert_returned_columns hook (overrides the inherited RETURNING-row -> hashref default). $col is the source's first is_auto_increment column, falling back to the first PK column not supplied in %to_insert. The legacy ->last_insert_id side-effect is preserved. create_async / Row::insert_async fold the hashref back via _store_inserted_columns.
- select_async / select_single_async shapes (ADR 0031 §3)
- select_async resolves with the raw row arrayrefs (cursor ->all shape) and select_single_async with a single row arrayref, matching the sync cursor shape and what _inflate_fetched_rows / _construct_results consume.
- Future then auto-wrap (ADR 0031 §4)
- The backend Future is plain Future (perl-Future), whose ->then natively auto-wraps a plain return into a resolved Future -- compliance is transitive. Documented in POD and verified by t/storage-facade-mock.t.
- Packaging
- Renamed distribution DBIO-MySQL-Async to DBIO-MySQL-EV and namespace DBIO::MySQL::Async to DBIO::MySQL::EV. The EV::MariaDB driver is hard-wired to the EV event loop; the DBIO::MySQL::Async namespace is freed for a future loop-agnostic driver built on DBIO::Async::Storage. CPAN namespace migration — the old distribution stays on CPAN. No behaviour change.
- Tests
- Add maint/k8s/mysql-pod.yaml (mysql:8.0, mysql_native_password forced so the libmariadb-based clients authenticate over a plain port-forward) for live integration testing, and DBIO::MySQL::EV::TestHarness (installable, gated on DBIO_TEST_MYSQL_DSN, mirrors the PostgreSQL-EV harness API).
- Fixed test/harness-only bugs surfaced on the first live run (no production runtime change): PoolBase::acquire can hand off an EV::MariaDB handle before its async connect completes when no on_connect action is configured, so pooled-connection tests now wait for readiness explicitly (_await_connected) or warm the pool first; a live SELECT used an invalid bare '*' after a named select-expression and a plain-string column alias that got backtick-quoted into an unknown column; and a broker test now asserts the achievable truth (broker attaches to the sync storage; a schema-level connect() cannot select an async mode and attach a broker at the same time). karr #19, #21.
- Dependencies
- Requires core DBIO >= 0.900001 (family-wide version alignment)
- Project
- Added SECURITY.md (CPAN Security Group guidelines v1.5.0)
Modules
Async MySQL/MariaDB storage for DBIO via EV::MariaDB
MySQL/MariaDB connection-info utilities for DBIO async driver
EV::MariaDB connection pool for DBIO
Query execution wrapper for DBIO MySQL async storage
Async MySQL/MariaDB storage driver using EV::MariaDB
Reusable live-MySQL harness for EV async on_connect-replay tests
Pinned connection context for an async MySQL/MariaDB transaction