Subject: | BlockRunner not handling rollback-during-commit gracefully |
(#dbix-class, 2019-06-13)
Hopefully this is enough information. Because the issue involves interacting with a real db driver, I don't think it's possible to easily write this up as a unit test.
10:22 < ether> bah, it looks like deferred constraint checking is not well-handled in DBD::Pg...
10:22 < ether> I've got a bunch of statements wrapped in a transaction. some of the constraints deferred until that 'COMMIT' is executed...
10:23 < ether> I'm using txn_do, so a ROLLBACK is then triggered
10:23 < ether> and then I get a warning: rollback ineffective with AutoCommit enabled at /Users/ether/.perlbrew/libs/26.3@std/lib/perl5/DBIx/Class/Storage/DBI.pm line 1651.
10:24 < ether> which is a red herring in this case, because everything did actually get successfully rolled back
10:24 < ether> I can't find this warning string in .pm code so it must be in XS somewhere, in the driver itself
10:25 < ether> all I can think to do is to set up a temporary __WARN__ handler to swallow this warning, where I set up the txn_do
10:26 < ether> ah, it's in Driver.xst in the DBI distribution
10:27 < ether> https://metacpan.org/source/TIMB/DBI-1.642/Driver.xst#L305-312
10:28 < ether> I'm not quite sure how one could patch this for this situation, though
10:29 < ether> perhaps I could temporarily turn off AutoCommit on the dbh
10:29 < ether> or should DBIx::Class::Storage::txn_rollback be doing this?
10:30 < alh> Why is autocommit on if you're in a tx?
10:31 < ether> I don't think it get turned off for transactions
10:34 < mohawk> i thought it did
10:34 < ether> I don't have this problem for normal rollbacks inside transactions -- this one is special because we already issued a 'COMMIT' and the exception (triggering a rollback) happened during
that execution
10:34 < ether> (because of the deferred constraints)
10:35 < mohawk> sounds like DBI itself might be turning autocommit back on a bit prematurely to me
10:35 <@mst> oh, that's interesting
10:35 <@mst> mohawk: naw
10:36 < ether> ?
10:36 <@mst> this'll be "DBIC tries to rollback on exception, it hadn't occurred to DBIC that commit could be what's throwing it"
10:36 <@mst> I'd bet
10:36 <@mst> which means it's not really DBD::Pg's fault
10:37 < ether> if it's DBIx::Class's fault, that means I should be able to patch around it
10:37 < ether> adding a __WARN__ handler is hacky but perhaps safest
10:38 <@mst> BlockRunner.pm seems to be where it's getting confused
10:40 < mohawk> mst, does that mean DBIC itself is changing AutoCommit?
10:40 <@mst> what
10:41 <@mst> of course it is, that's how transactions *work*
10:41 < ether> I thought the 'start transaction' statement might override AutoCommit
10:41 < mohawk> the last part i am aware of. my mental model was that DBI (not DBIC) took care of all of that, and DBIC just called txn_do (which i will now confirm is a DBI thing by looking that up)
10:42 <@mst> no, txn_do I invented
10:42 <@mst> however, calling $dbh->begin_work will IIRC set AutoCommit to 0
10:43 < mohawk> mst, thanks - that was where my model was wrong
10:44 < hobbs> txn_do appeared in DBIC and then was extracted into a couple modules which can provide the same thing on top of DBI without the rest of DBIC
10:44 <@mst> right
10:44 <@mst> because once I'd implemented it, it was obviously superior, so in the true spirit of open source people stole it enough times that it just started to seem obvious to people