DBIO-Async

 view release on metacpan or  search on metacpan

lib/DBIO/Async/Pool.pm  view on Meta::CPAN




sub new {
  my ($class, %args) = @_;
  my $storage = delete $args{storage};
  croak('storage required') unless $storage;

  my $self = $class->SUPER::new(%args);
  $self->{storage} = $storage;
  Scalar::Util::weaken($self->{storage}) if ref $self->{storage};
  return $self;
}


sub acquire {
  my $self = shift;
  return $self->SUPER::acquire->then(sub {
    my $conn = shift;
    return $self->_await_conn_ready($conn);
  });

lib/DBIO/Async/Pool.pm  view on Meta::CPAN


  my $pool = DBIO::Async::Pool->new(
      storage  => $storage,       # required
      conninfo => $conninfo,      # or conninfo_provider
      size     => 10,
      on_error => sub { warn $_[0] },
  );

Like L<DBIO::Storage::PoolBase/new>, but requires a C<storage> argument
(the L<DBIO::Async::Storage> that owns this pool). The storage reference
is weakened to avoid a cycle (storage holds pool, pool holds storage).

=head2 acquire

Like L<DBIO::Storage::PoolBase/acquire>, but the resolved Future does not
complete until the connection is actually ready for queries. This
correctly handles drivers where connection construction returns before
the async connect finishes (e.g. libpq's C<PQconnectStart>).

Readiness is checked via L</_await_conn_ready>, which delegates to the
Storage's L<DBIO::Async::Storage/_await_conn_ready>.

t/04-bind-release.t  view on Meta::CPAN

use strict;
use warnings;
use Test::More;
use Scalar::Util 'weaken';
use Future;

# OFFLINE regression test for the "async bind-value leak" concern.
# Ported from dbio-postgresql-async t/05-bind-release.t.
#
# WHAT THIS TEST PROVES: bind values issued through the async query
# path are retained only by the issuing scope's lexical, not by any
# storage/pool cache. Once that scope ends, the bind arrayref is freed.
# This is a pure Perl reference-graph question -- no DB needed.
#

t/04-bind-release.t  view on Meta::CPAN

# --- 1. single pooled query: bind released once the future completes ---

{
  my $storage = new_storage;
  my $pool = $storage->pool;

  my $weak;
  my $f;
  {
    my $bind = [ 'payload' x 64 ];
    weaken($weak = $bind);
    $f = $storage->_query_async('SELECT $1', $bind);
  }
  # The issuing-scope strong lexical dies here.

  # Complete the query on the FakeConn4.
  my $conn = $pool->{_connections}[0];
  $conn->complete_one;
  $f->get;

  ok !defined $weak,

t/04-bind-release.t  view on Meta::CPAN

  my $storage = new_storage;
  my $pool = $storage->pool;

  # Acquire a connection manually to simulate a pinned transaction conn.
  my $conn = $pool->acquire->get;

  my $weak;
  my $f;
  {
    my $bind = [ 'txn-payload' x 64 ];
    weaken($weak = $bind);
    $f = $storage->_query_async_pinned($conn, 'SELECT $1', $bind);
  }

  $conn->complete_one;
  $f->get;

  ok !defined $weak,
    'pinned (txn) query: bind arrayref is freed after completion too';
}

t/04-bind-release.t  view on Meta::CPAN


  # Pre-spawn enough connections for N concurrent queries.
  # Pool size is 5 by default; use 3 queries to stay within.
  my $N = 3;
  my @weak;
  my @f;
  for my $i (1 .. $N) {
    my $w;
    {
      my $bind = [ "row$i" x 32 ];
      weaken($w = $bind);
      push @f, $storage->_query_async("SELECT \$1 -- $i", $bind);
    }
    push @weak, $w;
  }

  my $held_inflight = grep { defined } @weak;
  is $held_inflight, 0,
    "no bind arrayref is retained while $N queries are in-flight "
    . '(no per-pool/per-future bind cache)';



( run in 1.356 second using v1.01-cache-2.11-cpan-995e09ba956 )