DBIO-PostgreSQL-EV

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for DBIO-PostgreSQL-EV

0.900001  2026-07-12
    * Documentation
        - DBIO::PostgreSQL::EV POD: replaced the stale async_backend() opt-in
          story with the actual { async => 'ev' } per-connection opt-in
          (ADR 0030); SYNOPSIS now shows loading the PostgreSQL::EV component
          and connecting with the async option instead of implying async runs
          without either. (karr #23, flagged during #22)

    * Pool
        - DBIO::PostgreSQL::EV::Pool adopts core DBIO::Storage::PoolBase's new
          connection-readiness seam (karr #75, hoisted from this pool's own
          karr #9 fix). Dropped the local acquire() override -- the base now
          gates every acquire() through _connection_ready_future for all
          three paths (spawn/idle-reuse/waiter) -- and the private {_ready}
          refaddr bookkeeping, replaced with core's
          _register_connection_ready/_connection_ready_lookup helpers;
          _shutdown_connection no longer has to clean the table up itself
          (the base's shutdown() does it centrally). Behaviour unchanged;
          this mirrors the reference fix dbio-mysql-ev's karr #20 was
          missing and just adopted the same way.

    * Packaging
        - Renamed dist DBIO-PostgreSQL-Async -> DBIO-PostgreSQL-EV and the
          DBIO::PostgreSQL::Async::* namespace -> DBIO::PostgreSQL::EV::*. The
          EV::Pg/libpq-async driver is now named for its event loop; the ::Async
          namespace is reserved for a future loop-agnostic driver. The old dist
          stays on CPAN — this is a namespace migration, not a behaviour change.

    * Storage
        - DBIO::PostgreSQL::EV::Storage is now a thin transport over core
          DBIO::Storage::Async instead of reimplementing the whole async surface
          (Storage.pm 1109 -> 938 lines). It inherits the shared machinery —
          select/insert/update/delete_async, _run_crud, txn_do_async, the
          insert-RETURNING overlay, pipeline, the sync fallbacks and SQL
          generation — and keeps only the EV/libpq wire seams plus EV value-add
          (listen/notify, copy_in, deploy_async). (karr #22, core #70)
        - Async is opt-in per connection via { async => 'ev' } (ADR 0030):
          loading the PostgreSQL::EV component is an inert marker, and the EV
          backend is reached explicitly through
          MyApp::Schema->connect($dsn, $u, $p, { async => 'ev' }). The async
          storage is embedded as the async backend of the sync storage rather
          than hijacking storage_type; it weakens its schema ref to break the
          embed cycle and accepts the sync driver's DBI-form connect_info. The
          legacy async_backend() instance method and async_fallback chain are
          gone — a *_async call on a sync instance now croaks explicitly rather
          than silently degrading. (ADR 0028, ADR 0030, karr #59)
        - insert_async resolves with a returned-columns HASHREF, not a positional
          row (ADR 0031 §3): _run_crud appends RETURNING * to the INSERT and folds
          the returned row onto the source's declared column order, so
          create_async / Row::insert_async see the autoinc PK on the row.
          select_async resolves with row arrayrefs (cursor ->all shape),
          select_single_async with a single row arrayref / undef; documented in
          POD. The backend Future is plain perl-Future, whose ->then auto-wraps a
          plain return, so no explicit Future->done is needed in *_async
          callbacks (ADR 0031 §4). (karr #18)
        - transport_capabilities advertises on_connect_replay, listen, notify,
          copy and pipeline — each backed by a real implementation, none
          claimed-but-absent. (karr #22)

    * SQL
        - Async CRUD translates the SQL maker's '?' placeholders into PostgreSQL
          positional '$N' before handing SQL to libpq (EV::Pg->query_params only
          understands '$N') via the _transform_sql seam. The shared
          DBIO::PostgreSQL::SQLMaker keeps emitting '?' for the sync DBI driver;
          the translation is async-only and preserves the '@?' jsonpath operator
          and '?' inside quoted literals. Without it a bound WHERE/SET/VALUES
          reached Postgres as '... = ?' and died with a syntax error.
          (karr #7, core #70, ADR 0032)

    * Deploy
        - deploy_async: deploy a schema through DBIO's native deploy pipeline,
          executing every generated DDL statement on EV::Pg inside a single
          async transaction (COMMIT on success, ROLLBACK on the first DDL
          error). The add_drop_table option prepends DROP TABLE IF EXISTS ...
          CASCADE for every regular table (views and non-plain-identifier names
          skipped) so a re-run on a populated database stays idempotent. A
          blocking deploy() wrapper drives it via ->get for scripts. Covered by
          t/21-deploy-async-live.t (live).

    * Connection pool
        - on_connect_do / on_connect_call now replay on every EV pooled
          connection (e.g. AGE's load_age): pool() passes storage => $self so
          core's pool setup fires, and each on_connect statement is driven to
          completion on the EV loop. (karr #22, karr #69)
        - Pooled acquire waits for the connection to finish its async connect
          before resolving, so the first CRUD call on a cold pool no longer dies
          with "not connected"; idle reuse stays immediate and a failed connect
          fails the dependent query instead of hanging. (karr #9)
        - Pool acquire order is FIFO (core PoolBase shift/push), verified by a
          pg_backend_pid() rotation test. (karr #20)
        - Guarded _shutdown_connection against undef at global destruction — no
          more "Use of uninitialized value" from Pool.pm on teardown.

    * Bug fixes
        - txn_do_async no longer hangs. Its COMMIT/ROLLBACK chain was built off
          the coderef's Future, which Future.pm holds only weakly, so the chain
          was garbage-collected ("lost a sequence Future") before COMMIT/ROLLBACK
          could run — the transaction Future never resolved and the event loop
          busy-spun at ~100% CPU. The chain now completes the outer Future
          directly via on_done/on_fail and retains the coderef Future until it
          settles. (karr #10)
        - copy_in no longer races the pooled-connection release: the connection



( run in 1.778 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )