I have next code:
my $savepoint = $c->db->txn_scope_guard;
return $self->render( 'subnet/create', error => [ create => $@ ],
servers => $self->rows( 'Server' )->lookup,
) unless $subnet = eval{ $self->rows( 'Subnet' )->create( $subnet ) };
$savepoint->commit;
Here rows
is Mojolicious helper which provides access to data.
sub model {
my( $c, $table_name ) = (shift,shift);
return $c->db->resultset( $table_name );
}
And ->db
is also helper:
sub db { return $schema
//= DBIx::Class::Schema->connect( $DB->{ DSN }, @$DB{ qw/ USER PASS / }, {
AutoCommit => 1,
RaiseError => 1,
quote_char => '"',
})
});
When I create $subnet
and unique constraint occurs (here has no matter which constraint occur, actually in case of any exception) I got the error:
DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed: ERROR: current transaction is aborted, commands ignored until end of transaction block [for Statement "SELECT "me"."id", "me"."hostname" FROM "servers" "me" ORDER BY hostname"] at ...
This is when I catch exception with eval{ ... }
the current transaction is aborted and I can not do $self->rows( 'Server' )->lookup
Is there a way to access server data after exception occur?
Seems I found the answer, because read error message more carefully:
... commands ignored until end of transaction block
So I force the end for transaction block when exception occur:
$c->db->txn_rollback;
The code:
my $savepoint = $c->db->txn_scope_guard;
unless( $subnet = eval{ $self->rows( 'Subnet' )->create( $subnet ) } ) {
my $e = $@; # $@ may be changed before `create => $@`
undef $savepoint; # Or the same: $c->db->txn_rollback;
return $self->render( 'subnet/create', error => [ create => $e ],
servers => $self->rows( 'Server' )->lookup,
);
}
$savepoint->commit;