Scope::Guard for db rollback

jozef on 2008-07-17T10:15:51

For the first time I used Scope::Guard and I like the idea. I used it to always issue database rollback if something goes wrong, some exception, in DBIx::Class ResultSet function. Then when calling this function I can wrap it in eval {}; block and don't need to care about the begin/commit/rollback stuff.

sub do_some_database_stuff : ResultSet {
    my $rs   = shift;
    
    # begin transaction
    $rs->result_source->schema->txn_begin;

# trigger rollback if we leave the function unexpecticly my $make_sure_we_rollback = Scope::Guard->new(sub{ local $@; # we don't want txn_rollback to mess up the $EVAL_ERROR $rs->result_source->schema->txn_rollback; });

# # insert, deletes, updates ... #

# commit transaction when all passed $rs->result_source->schema->txn_commit; $make_sure_we_rollback->dismiss; return $some_created_rows; }


Manually doing local $@

jplindstrom on 2008-07-17T12:26:33

I think that any module doing things similar to Scope::Guard (Perl::AtEndOfScope, etc) that doesn't deal with, or even mentions, the risks with eval/die isn't really doing its job.

I say this because it's not really obvious that there might be a problem, but the consequences when things go wrong are subtle and dire (silenced exceptions go untrapped).

Dealing with exceptions being thrown is simply a complication inherent to the problem being solved.

(btw Perl::AtEndOfScope does this correctly now)

How many times has this been written?

btilly on 2008-07-18T00:25:54

I wrote ReleaseAction years ago. ReleaseAction was not the first - Abigail wrote End well before I wrote that. And now I've just learned of 2 more modules that do the same thing!

Re:How many times has this been written?

jozef on 2008-07-18T07:50:56

Well there are just too many modules in CPAN... The Scope::Guard was shown in "Perl Hacks: Tips & Tools for Programming, Debugging, and Surviving" book as hack #88.

In the "See Also" of Scope::Guard there are even more of "those kinds" - Hook::LexWrap, Hook::Scope, Sub::ScopeFinalizer, Object::Destroyer ...

Which one is the "best"?