[email protected] (Florian Weimer) writes: > Is there are ready-to-use transaction wrapper for DBD:Pg? I'm looking > for somehting which can be used like this: > > my $connect_args = [$data_source, $username, $auth, \%attr]; > transact $connect_args, sub { > my ($dbh) = @_; > $dbh->begin_work; > ... > $dbh->commit; > }; > > The transact subroutine should abort the transaction if the passed sub > dies. For certain exceptions, the sub should be called again to retry > the transaction. The database handle should be cached. > > This is somewhat PostgreSQL-specific because there are three cases: > permanent errors (such as SQL syntax errors, or non-SQL exceptions), > transient errors which will go away when the transaction is retried > within the same connection (such as serialization failures and certain > types of UNIQUE constraint violations), and errors which will likely go > away when the transaction is retried with a fresh connection (due to > server restart, for example). > > This is not very difficult to write as such, but getting the error code > list right is a bit delicate.
There is no way in heaven or hell to deal cleanly with 'connection aborts' using the stock DBD::Pg because that won't consistently inform an application that 'a possibly transient communication problem ocurred' (let alone providing even more specialized error information). I happen to know this because I have implemented a couple of application-specific facilities for dealing transparently with such transient failures in the last couple of years[*] and this always involved another round of dbdimp.c changes when the thing blew up for another time in another different place. I think I have finally managed to nail that for the DBD::Pg I'm using, though, and a 'public patch' is available here: https://rt.cpan.org/Public/Bug/Display.html?id=66792 [*] My general opinion on 'third-party code written to solve development problems' is that it is generally not worth the effort to become familiar with that, especially considering that adapting or at least fixing it will become necessary at some point, except if using it means saving a significant amount of coding effort, with significant supposed to mean '>> 1000 LOC just to provide the required functionality'. Typically, what is actually required will need a few hundred lines of code and in this case, the problems lurking in the (also typically) thousands if not ten or even hundred thousands of lines of code of the 'one size fits all two times plus a kitchen sink' 'seriously bored programmer' solution are not worth dealing with.
