The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

DBIx::TransactionManager::Distributed;

VERSION

0.01

DESCRIPTION

Generic database handling utilities.

Currently provides a minimal database handle tracking facility, allowing code to request a transaction against all active database handles.

SYNOPSIS

use DBIx::TransactionManager::Distributed qw(register_dbh release_dbh txn);
my $dbh1 = DBI->connect('dbi:Pg', '', '', { RaiseError => 1});
my $dbh2 = DBI->connect('dbi:Pg', '', '', { RaiseError => 1});
my $dbh3 = DBI->connect('dbi:Pg', '', '', { RaiseError => 1});

register_dbh(category1 => $dbh1);
register_dbh(category1 => $dbh2);
register_dbh(category2 => $dbh2);
register_dbh(category2 => $dbh3);

txn { $dbh1->do('update ta set name = "a"'); $dbh2->do('insert into tb values (1)') } 'category1';
txn { $dbh2->do('update tc set name = "b"'); $dbh3->do('insert into td values (2)') } 'category2';

release_dbh(category1 => $dbh1);
release_dbh(category1 => $dbh1);
release_dbh(category2 => $dbh2);
release_dbh(category3 => $dbh3);

register_dbh

Records the given database handle as being active and available for running transactions against.

Expects a category (string value) and DBI::db instance.

Returns the database handle.

Example:

sub _dbh {
    my $dbh = DBI->connect('dbi:Pg', '', '', { RaiseError => 1});
    return DBIx::TransactionManager::Distributaed::register_dbh(category => $dbh);
}

release_dbh

Marks the given database handle as no longer active - it will not be used for any further transaction requests via "txn".

Returns the database handle.

Example:

sub DESTROY {
    my $self = shift;
    return if ${^GLOBAL_PHASE} eq 'DESTRUCT';
    DBIx::TransactionManager::Distributaed::release_dbh($self->dbh)->disconnect;
}

_remove_dbh_from_category

Helper function to reduce common code - removes the given $dbh from a single category.

Used internally.

dbh_is_registered

Returns true if the provided database handle has been registered already.

Used when registering a handle acquired via "connect_cached" in DBI.

register_dbh($category => $dbh) unless dbh_is_registered($category => $dbh);

register_cached_dbh

Records the given database handle created via "connect_cached" in DBI as being active and available for running transactions against.

Expects a category (string value) and DBI::db instance.

Returns the database handle.

Example:

sub _dbh {
    my $dbh = DBI->connect_cached('dbi:Pg', '', '', { RaiseError => 1});
    return register_cached_dbh('category' => $dbh);
}

txn

Runs the given coderef in a transaction.

Expects a coderef and one or more database handle categories.

Will call "begin_work" in DBI for every known database handle in the given category, run the code, then call "commit" in DBI on success, or "rollback" in DBI on failure.

Will raise an exception on failure, or return an empty list on success.

Example:

txn { dbh()->do('NOTIFY something') } 'category';

WARNING: This only applies transactions to known database handles. Anything else - Redis, cache layers, files on disk - is out of scope. Transactions are a simple "begin_work" in DBI / "commit" in DBI pair, there's no 2-phase commit or other distributed transaction co-ordination happening here.

_check_fork

Test whether we have forked recently, and invalidate all our caches if we have.

Returns true if there has been a fork since last check, false otherwise.

SEE ALSO

These modules are also handling scope-based transaction. The main difference is this one operates across database handles with different categories.