I've been writing some Perl DBI code which involves some fairly involved error handling; I've been looking for a way to roll back transactions neatly when certain errors happen.
I very nearly reinvented the concept of a 'transaction scope guard' which I now find is implemented in DBIx::Class (with Scope::Guard implementing a more general version). A lexical variable can be used to detect in which cases a transaction should be ended, because the object it points to will get DESTROYed when it goes out of scope. Some rough code to illustrate the concept is below.
# $fallback controls whether we use nested transactions,
# which is slower but lets us commit all the other lines in the batch.
sub process_batch {
my $fallback = shift;
# This catches any exception handling that makes us leave the function.
# The DESTROY method of $transaction contains $db->rollback()
my $transaction = $db->txn_scope_guard();
for (1..2000) {
# File access error will get thrown to outside of function,
# so the transaction will be rolled back.
my $line = get_next_line();
last unless $line;
my $parsed;
eval {$parsed = parse_line($line)};
if ($@) {
# Handle line parsing errors here without interfering with
# DB error handling.
warn "Could not parse $line\n";
next;
}
# here's the actual db code
eval {
$db->savepoint() if $fallback;
$db->process_one_line($parsed);
}
if ($@) {
if ($fallback) {
# Just roll back to savepoint. Transaction continues.
$db->rollback_to_savepoint();
} else {
# Propagate error outside of function, ending transaction.
die $@;
}
}
}
$transaction->commit();
}
The advantage is that rollback code can be kept in one place, and not repeated all over the various error handling cases.
I had actually gone off this idea, because I couldn't see any documentation defining exactly when the DESTROY method gets called in Perl. But given it's got into DBIx::Class, it must be fine! I also prefer their API over what I was considering implementing; the transaction object that gets returned will handle only commit(), not any other database calls.
Posted: 25 Oct 2009 01:11 |
| < | October 2009 | > | ||||
| Su | Mo | Tu | We | Th | Fr | Sa |
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tim Retout tim@retout.co.uk
JabberID: tim@retout.co.uk
I'm afraid I have turned off comments for this blog, because of all the spam. Let's face it, I didn't read them anyway. Feel free to email me.