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;
}
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)
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"?