From: Ash Berlin Date: Sun, 10 Feb 2008 17:31:27 +0000 (+0000) Subject: Add txn_scope_guard method/object X-Git-Tag: v0.08010~2 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=1bc193ac4c3bb934d1877e49bf7c465fc82815d6;p=dbsrgits%2FDBIx-Class.git Add txn_scope_guard method/object --- diff --git a/Changes b/Changes index 624473b..1b5b144 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,8 @@ Revision history for DBIx::Class + - Created Storage::TxnScopeGuard object and txn_scope_guard methods + on Schema and Storage as an alternative way of doing transactions + 0.08009 2008-01-20 13:30 - Made search_rs smarter about when to preserve the cache to fix mm prefetch usage diff --git a/lib/DBIx/Class/Row.pm b/lib/DBIx/Class/Row.pm index 1fb852c..377e5e8 100644 --- a/lib/DBIx/Class/Row.pm +++ b/lib/DBIx/Class/Row.pm @@ -159,11 +159,9 @@ sub insert { %{$self->{_inflated_column} || {}}); if(!$self->{_rel_in_storage}) { - $source->storage->txn_begin; # The guard will save us if we blow out of this scope via die - - $rollback_guard = Scope::Guard->new(sub { $source->storage->txn_rollback }); + $rollback_guard = $source->storage->txn_scope_guard; ## Should all be in relationship_data, but we need to get rid of the ## 'filter' reltype.. @@ -246,8 +244,7 @@ sub insert { } } } - $source->storage->txn_commit; - $rollback_guard->dismiss; + $rollback_guard->commit; } $self->in_storage(1); diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index 09edb9b..c42f10a 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -734,6 +734,15 @@ sub txn_do { $self->storage->txn_do(@_); } +sub txn_scope_guard { + my $self = shift; + + $self->storage or $self->throw_exception + ('txn_scope_guard called on $schema without storage'); + + $self->storage->txn_scope_guard(@_); +} + =head2 txn_begin Begins a transaction (does nothing if AutoCommit is off). Equivalent to diff --git a/lib/DBIx/Class/Storage.pm b/lib/DBIx/Class/Storage.pm index cd29601..e298aa3 100644 --- a/lib/DBIx/Class/Storage.pm +++ b/lib/DBIx/Class/Storage.pm @@ -8,6 +8,7 @@ use base qw/DBIx::Class/; use Scalar::Util qw/weaken/; use Carp::Clan qw/^DBIx::Class/; use IO::File; +use DBIx::Class::Storage::TxnScopeGuard; __PACKAGE__->mk_group_accessors('simple' => qw/debug debugobj schema/); __PACKAGE__->mk_group_accessors('inherited' => 'cursor_class'); @@ -261,6 +262,16 @@ which allows the rollback to propagate to the outermost transaction. sub txn_rollback { die "Virtual method!" } +=head2 txn_scope_guard + +Return an object that does stuff. + +=cut + +sub txn_scope_guard { + return DBIx::Class::Storage::TxnScopeGuard->new($_[0]); +} + =head2 sql_maker Returns a C object - normally an object of class diff --git a/lib/DBIx/Class/Storage/TxnScopeGuard.pm b/lib/DBIx/Class/Storage/TxnScopeGuard.pm new file mode 100644 index 0000000..04978f9 --- /dev/null +++ b/lib/DBIx/Class/Storage/TxnScopeGuard.pm @@ -0,0 +1,79 @@ +package DBIx::Class::Storage::TxnScopeGuard; + +use strict; +use warnings; + +sub new { + my ($class, $storage) = @_; + + $storage->txn_begin; + bless [ 0, $storage ], ref $class || $class; +} + +sub commit { + my $self = shift; + + $self->[1]->txn_commit; + $self->[0] = 1; +} + +sub DESTROY { + my ($dismiss, $storage) = @{$_[0]}; + + $storage->txn_rollback unless $dismiss; +} + +1; + +__END__ + +=head1 NAME + +DBIx::Class::Storage::TxnScopeGuard + +=head1 SYNOPSIS + + sub foo { + my ($self, $schema) = @_; + + my $guard = $schema->txn_scope_guard; + + # Multiple database operations here + + $guard->commit; + } + +=head1 DESCRIPTION + +An object that behaves much like L, but hardcoded to do the +right thing with transactions in DBIx::Class. + +=head1 METHODS + +=head2 new + +Creating an instance of this class will start a new transaction. Expects a +L object as its only argument. + +=head2 commit + +Commit the transaction, and stop guarding the scope. If this method is not +called (i.e. an exception is thrown) and this object goes out of scope then +the transaction is rolled back. + +=cut + +=head1 SEE ALSO + +L. + +=head1 AUTHOR + +Ash Berlin, 2008. + +Insipred by L by chocolateboy. + +This module is free software. It may be used, redistributed and/or modified +under the same terms as Perl itself. + +=cut