From: John Napiorkowski Date: Wed, 28 May 2008 19:15:34 +0000 (+0000) Subject: created storage method to execute a coderef using master storage only, changed tnx_do... X-Git-Tag: v0.08240~402^2~35 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=c4d3fae2d68b67050e6f4a04031608506e9a18e8;p=dbsrgits%2FDBIx-Class.git created storage method to execute a coderef using master storage only, changed tnx_do to only use the master, wrote tests for both the above, wrote docs for both the above --- diff --git a/lib/DBIx/Class/Storage/DBI/Replicated.pm b/lib/DBIx/Class/Storage/DBI/Replicated.pm index 3bfbf60..c95a084 100644 --- a/lib/DBIx/Class/Storage/DBI/Replicated.pm +++ b/lib/DBIx/Class/Storage/DBI/Replicated.pm @@ -224,7 +224,6 @@ has 'write_handler' => ( update delete dbh - txn_do txn_commit txn_rollback sth @@ -374,6 +373,56 @@ sub all_storages { ); } +=head2 execute_reliably ($coderef, ?@args) + +Given a coderef, saves the current state of the L, forces it to +use reliable storage (ie sets it to the master), executes a coderef and then +restores the original state. + +Example: + + my $reliably = sub { + my $name = shift @_; + $schema->resultset('User')->create({name=>$name}); + my $user_rs = $schema->resultset('User')->find({name=>$name}); + }; + + $schema->storage->execute_reliably($reliably, 'John'); + +Use this when you must be certain of your database state, such as when you just +inserted something and need to get a resultset including it, etc. + +=cut + +sub execute_reliably { + my ($self, $coderef, @args) = @_; + + unless( ref $coderef eq 'CODE') { + $self->throw_exception('Second argument must be a coderef'); + } + + ##Get copy of master storage + my $master = $self->master; + + ##Get whatever the current read hander is + my $current = $self->read_handler; + + ##Set the read handler to master + $self->read_handler($master); + + ## do whatever the caller needs + eval { + $coderef->(@args); + }; + + if($@) { + $self->throw_exception("coderef returned an error: $@"); + } + + ##Reset to the original state + $self->schema->storage->read_handler($current); +} + =head2 set_reliable_storage Sets the current $schema to be 'reliable', that is all queries, both read and @@ -404,6 +453,19 @@ sub set_balanced_storage { $schema->storage->read_handler($write_handler); } +=head2 txn_do ($coderef) + +Overload to the txn_do method, which is delegated to whatever the +L is set to. We overload this in order to wrap in inside a +L method. + +=cut + +sub txn_do { + my($self, $coderef, @args) = @_; + $self->execute_reliably($coderef, @args); +} + =head2 connected Check that the master and at least one of the replicants is connected. @@ -550,11 +612,12 @@ sub disconnect { =head1 AUTHOR -Norbert Csongrádi + John Napiorkowski -Peter Siklósi +Based on code originated by: -John Napiorkowski + Norbert Csongrádi + Peter Siklósi =head1 LICENSE diff --git a/t/93storage_replication.t b/t/93storage_replication.t index 7617af3..7765767 100644 --- a/t/93storage_replication.t +++ b/t/93storage_replication.t @@ -2,13 +2,14 @@ use strict; use warnings; use lib qw(t/lib); use Test::More; +use Test::Exception; use DBICTest; BEGIN { eval "use Moose; use Test::Moose"; plan $@ ? ( skip_all => 'needs Moose for testing' ) - : ( tests => 50 ); + : ( tests => 57 ); } use_ok 'DBIx::Class::Storage::DBI::Replicated::Pool'; @@ -433,6 +434,52 @@ SKIP: { => "both replicants reactivated"; } +## Test the reliably callback + +ok my $reliably = sub { + + ok $replicated->schema->resultset('Artist')->find(5) + => 'replicant reactivated'; + +} => 'created coderef properly'; + +$replicated->schema->storage->execute_reliably($reliably); + +## Try something with an error + +ok my $unreliably = sub { + + ok $replicated->schema->resultset('ArtistXX')->find(5) + => 'replicant reactivated'; + +} => 'created coderef properly'; + +throws_ok {$replicated->schema->storage->execute_reliably($unreliably)} + qr/coderef returned an error: Can't find source for ArtistXX/ + => 'Bad coderef throws proper error'; + +## make sure transactions are set to execute_reliably + +ok my $transaction = sub { + + $replicated + ->schema + ->populate('Artist', [ + [ qw/artistid name/ ], + [ 666, "Children of the Grave"], + ]); + + ok my $result = $replicated->schema->resultset('Artist')->find(666); + +}; + +$replicated->schema->txn_do($transaction); + +## Make sure replication came back + +ok $replicated->schema->resultset('Artist')->find(5) + => 'replicant reactivated'; + ## Delete the old database files $replicated->cleanup;