NAME

DBIx::Connector::Pool - A pool of DBIx::Connector or its subclasses for asynchronous environment

SYNOPSIS

use Coro;
use AnyEvent;
use Coro::AnyEvent;
use DBIx::Connector::Pool;

my $pool = DBIx::Connector::Pool->new(
  initial    => 1,
  keep_alive => 1,
  max_size   => 5,
  tid_func   => sub {"$Coro::current" =~ /(0x[0-9a-f]+)/i; hex $1},
  wait_func => sub        {Coro::AnyEvent::sleep 0.05},
  attrs     => {RootClass => 'DBIx::PgCoroAnyEvent'}
);

async {
  my $connector = $pool->get_connector;
  $connector->run(
    sub {
      my $sth = $_->prepare(q{select isbn, title, rating from books});
      $sth->execute;
      my ($isbn, $title, $rating) = $sth->fetchrow_array;
      # ... 
    }
  );
};

Description

DBI is great and DBIx::Connector is a nice interface with good features to it. But when it comes to work in some asynchronous environment like AnyEvent you have to use something another with callbacks if you don't want to block your event loop completely waiting for data from DB. This module (together with DBIx::PgCoroAnyEvent for PostgreSQL or some another alike) was developed to overcome this inconvenience. You can write your "normal" DBI code without blocking your event loop.

This module requires some threading model and I know about only one really working Coro.

Methods

new
my $pool = DBIx::Connector::Pool->new(
  initial    => 1,
  keep_alive => 1,
  max_size   => 5,
  tid_func   => sub {"$Coro::current" =~ /(0x[0-9a-f]+)/i; hex $1},
  wait_func => sub        {Coro::AnyEvent::sleep 0.05},
  attrs     => {RootClass => 'DBIx::PgCoroAnyEvent'}
);

Creates new pool. Possible parameters:

initial

Initial number of connected connectors. This means also minimum of of connected connectors. It throws error if this minimum can not be met.

keep_alive

How long connector can live after it becomes unused. Initial connectors will live forever. -1 means no limit. 0 means collect it immediate. Positive number means seconds.

max_size

Maximum pool capacity. -1 means unlimited.

user
password
dsn
attrs

Data for DBIx::Connector->new function. This is the same as for DBI->connect. Usually you want to add some unblocking DBI subclass as RootClass attribute. Like RootClass => 'DBIx::PgCoroAnyEvent' for PostgreSQL.

connector_mode

Sets the default "Connection Modes" in DBIx::Connector attribute, which is used by run(), txn(), and svp() if no mode is passed to them. Defaults to "fixup".

tid_func

Thread identification function. Must return number. Good choice for Coro is

sub {"$Coro::current" =~ /(0x[0-9a-f]+)/i; hex $1}
wait_func

This function put get_connector into sleep to wait for a free connector in pool.

connector_base

In case you use some subclass of DBIx::Connector you have to point it out.

get_connector

Returns available connector. Returned object is a subclass of DBIx::Connector or subclass of connector_base.

The same thread will get the same already used connector until it's free. Function always wait for an available connector, it can't return undef.

When new connection can not be established an error is thrown or if max_size is greater than intial or equal to -1 then max_size will be automatically lowered to actually possible size.

collect_unused

Method marks unused and disconnects timed out connectors. It keeps minimum initial number of connectors connected. Intended to be used from timers events.

connected_size

Returns number of currently connected connectors.

$DBIx::Connector::Pool::Item::not_in_use_event

This package variable is a subroutine referenc which is called when connectors object is not in use anymore. You can use it together with wait_func to wake up a waiting for a free connector get_connector. For example:

my @pool_wait_queue;
$DBIx::Connector::Pool::Item::not_in_use_event = sub {
   if (my $wc = shift @pool_wait_queue) {
      $wc->ready;
   }
   $_[0]->used_now;
};
...
wait_func => sub {push @pool_wait_queue, $Coro::current; Coro::schedule;}   

SEE ALSO

BUGS

Currently this module tested only for PostgreSQL + Coro + AnyEvent.

AUTHOR

This module was written and is maintained by Anton Petrusevich.

Copyright and License

Copyright (c) 2016 Anton Petrusevich. Some Rights Reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.