sub discard_changes {
my ($self) = @_;
- delete $self->{_dirty_columns};
- return unless $self->in_storage; # Don't reload if we aren't real!
-
- my $reload = $self->result_source->resultset->find(
- map { $self->$_ } $self->primary_columns
- );
- unless ($reload) { # If we got deleted in the mean-time
- $self->in_storage(0);
- return $self;
- }
-
- %$self = %$reload;
-
- # Avoid a possible infinite loop with
- # sub DESTROY { $_[0]->discard_changes }
- bless $reload, 'Do::Not::Exist';
-
+ my $storage = $self->result_source->schema->storage;
+ $storage->reload_row($self);
return $self;
}
sub select_single { die "Virtual method!" }
+=head2 reload_row ($row)
+
+given a L<DBIx::Class::Row> object, 'reloads' it from the storage. This will
+destroy any existing changes you have not yet saved.
+
+=cut
+
+sub reload_row { die "Virtual method!" }
+
=head2 columns_info_for
Returns metadata for the given source's columns. This
return @row;
}
+sub reload_row {
+ my ($self, $row) = @_;
+ delete $row->{_dirty_columns};
+ return unless $row->in_storage; # Don't reload if we aren't real!
+
+ my $reload = $row->result_source->resultset->find(
+ map { $row->$_ } $row->primary_columns
+ );
+ unless ($reload) { # If we got deleted in the mean-time
+ $row->in_storage(0);
+ return $row;
+ }
+
+ $row = %$reload;
+
+ # Avoid a possible infinite loop with
+ # sub DESTROY { $_[0]->discard_changes }
+ bless $reload, 'Do::Not::Exist';
+
+ return $row;
+}
+
=head2 sth
=over 4
sth
deploy
schema
+ reload_row
/],
);
my $name = shift @_;
$schema->resultset('User')->create({name=>$name});
my $user_rs = $schema->resultset('User')->find({name=>$name});
+ return $user_rs;
};
- $schema->storage->execute_reliably($reliably, 'John');
+ my $user_rs = $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.
$self->read_handler($master);
## do whatever the caller needs
+ my @result;
+ my $want_array = wantarray;
+
eval {
- $coderef->(@args);
+ if($want_array) {
+ @result = $coderef->(@args);
+ }
+ elsif(defined $want_array) {
+ ($result[0]) = ($coderef->(@args));
+ } else {
+ $coderef->(@args);
+ }
};
+ ##Reset to the original state
+ $self->schema->storage->read_handler($current);
+
+ ##Exception testing has to come last, otherwise you might leave the
+ ##read_handler set to master.
+
if($@) {
$self->throw_exception("coderef returned an error: $@");
+ } else {
+ return $want_array ? @result : $result[0];
}
-
- ##Reset to the original state
- $self->schema->storage->read_handler($current);
}
=head2 set_reliable_storage
$self->execute_reliably($coderef, @args);
}
+=head2 reload_row ($row)
+
+Overload to the reload_row method so that the reloading is always directed to
+the master storage.
+
+=cut
+
+around 'reload_row' => sub {
+ my ($reload_row, $self, $row) = @_;
+ $self->execute_reliably(sub {
+ $self->$reload_row(shift);
+ }, $row);
+};
+
=head2 connected
Check that the master and at least one of the replicants is connected.
eval "use Moose; use Test::Moose";
plan $@
? ( skip_all => 'needs Moose for testing' )
- : ( tests => 57 );
+ : ( tests => 71 );
}
use_ok 'DBIx::Class::Storage::DBI::Replicated::Pool';
} => 'created coderef properly';
throws_ok {$replicated->schema->storage->execute_reliably($unreliably)}
- qr/coderef returned an error: Can't find source for ArtistXX/
+ qr/Can't find source for ArtistXX/
=> 'Bad coderef throws proper error';
+## Make sure replication came back
+
+ok $replicated->schema->resultset('Artist')->find(3)
+ => 'replicant reactivated';
+
## make sure transactions are set to execute_reliably
ok my $transaction = sub {
+ my $id = shift @_;
+
$replicated
->schema
->populate('Artist', [
[ qw/artistid name/ ],
- [ 666, "Children of the Grave"],
+ [ $id, "Children of the Grave"],
]);
- ok my $result = $replicated->schema->resultset('Artist')->find(666);
+ ok my $result = $replicated->schema->resultset('Artist')->find($id);
+ ok my $more = $replicated->schema->resultset('Artist')->find(1);
+
+ return ($result, $more);
};
-$replicated->schema->txn_do($transaction);
+## Test the transaction with multi return
+{
+ ok my @return = $replicated->schema->txn_do($transaction, 666)
+ => 'did transaction';
+
+ is $return[0]->id, 666
+ => 'first returned value is correct';
+
+ is $return[1]->id, 1
+ => 'second returned value is correct';
+}
+
+## Test that asking for single return works
+{
+ ok my $return = $replicated->schema->txn_do($transaction, 777)
+ => 'did transaction';
+
+ is $return->id, 777
+ => 'first returned value is correct';
+}
+
+## Test transaction returning a single value
+
+{
+ ok my $result = $replicated->schema->txn_do(sub {
+ ok my $more = $replicated->schema->resultset('Artist')->find(1);
+ return $more;
+ }) => 'successfully processed transaction';
+
+ is $result->id, 1
+ => 'Got expected single result from transaction';
+}
## Make sure replication came back
-ok $replicated->schema->resultset('Artist')->find(5)
+ok $replicated->schema->resultset('Artist')->find(1)
=> 'replicant reactivated';
+
+## Test Discard changes
+
+{
+ ok my $artist = $replicated->schema->resultset('Artist')->find(2)
+ => 'got an artist to test discard changes';
+
+ ok $artist->discard_changes
+ => 'properly discard changes';
+}
## Delete the old database files
$replicated->cleanup;