Database-Async

 view release on metacpan or  search on metacpan

lib/Database/Async.pm  view on Meta::CPAN

In L<DBI>:

 my $sth = $dbh->prepare(q{select * from something where id = ?});
 for my $id (1, 2, 3) {
  $sth->bind(0, $id, 'bigint');
  $sth->execute;
  while(my $row = $sth->fetchrow_hashref) {
   print $row->{name} . "\n";
  }
 }

In L<Database::Async>:

 my $sth = $db->prepare(q{select * from something where id = ?});
 (Future::Utils::fmap_void  {
  my ($id) = @_;
  $sth->bind(0, $id, 'bigint')
   ->then(sub { $sth->execute })
   ->then(sub {
    $sth->row_hashrefs
     ->each(sub {
      print $_->{name} . "\n";
     })->completed
   })
 } foreach => [1, 2, 3 ])->get;

=cut

use mro;
no indirect;

use Future::AsyncAwait qw(:experimental);
use Syntax::Keyword::Try;

use URI;
use URI::db;
use Module::Load ();
use Scalar::Util qw(blessed);

use Database::Async::Engine;
use Database::Async::Pool;
use Database::Async::Query;
use Database::Async::StatementHandle;
use Database::Async::Transaction;

use Log::Any qw($log);

=head1 METHODS

=cut

=head2 transaction

Resolves to a L<Future> which will yield a L<Database::Async::Transaction>
instance once ready.

=cut

async sub transaction {
    my ($self, @args) = @_;
    Scalar::Util::weaken(
        $self->{transactions}[@{$self->{transactions}}] =
            my $txn = Database::Async::Transaction->new(
                database => $self,
                @args
            )
    );
    await $txn->begin;
    return $txn;
}

=head2 txn

Executes code within a transaction. This is meant as a shorter form of
the common idiom

 $db->transaction
    ->then(sub {
     my ($txn) = @_;
     Future->call($code)
      ->then(sub {
       $txn->commit
      })->on_fail(sub {
       $txn->rollback
      });
    })

The code must return a L<Future>, and the transaction will only be committed
if that L<Future> resolves cleanly.

Returns a L<Future> which resolves once the transaction is committed.

=cut

async sub txn {
    my ($self, $code, @args) = @_;
    my $txn = await $self->transaction;
    try {
        my @data = await Future->call(
            $code => ($txn, @args)
        );
        await $txn->commit;
        return @data;
    } catch {
        my $exception = $@;
        try {
            await $txn->rollback;
        } catch {
            $log->warnf("exception %s in rollback", $@);
        }
        die $exception;
    }
}

=head1 METHODS - Internal

You're welcome to call these, but they're mostly intended
for internal usage, and the API B<may> change in future versions.

=cut



( run in 0.841 second using v1.01-cache-2.11-cpan-39bf76dae61 )