Transazioni Perl DBIx :: Class con commit mancante
Faccio fatica con un comportamento incoerente del modulo Perl DBIx :: Class. Ho scritto una semplice classe Perl pura, che definisce il membro della classe 'schema', che è solo un riferimento a un oggetto DBIx :: Class :: Schema pre inizializzato / connesso e un metodo per aggiungere alcuni dati al database:
sub new {
my $class = shift; my $params;
if(1 == scalar @_ && 'HASH' eq ref($_[0])) { $params = shift;
} else {
my %params = @_;
$params = \%params; } my $self = {
schema => $params->{schema} }; bless $self, $class; return $self;
}
sub addToQueue {
my $self = shift; my $params;
if(1 == scalar @_ && 'HASH' eq ref($_[0])) { $params = shift;
} else {
my %params = @_;
$params = \%params; } #some parameter constraints checks .... $self->{schema}->txn_do(sub {
$self->{schema}->resultset('SOME_QUEUE')->create($params);
});
# this row is necessary if this method is called from programs, which uses moose
$self->{schema}->txn_commit();
return;
}
Se chiamo il metodo addToQueue da un programma Perl (usa Moose), devo aggiungere la riga di codice
self->{schema}->txn_commit();
per attivare davvero il comando DB commit. Se chiamo il metodo da un altro programma Perl (non usa Moose) il codice fallisce con il messaggio:
Uso del valore non inizializzato $ msg in sostituzione (s ///) in /usr/local/share/perl/5.20.2/DBIx/Class/Exception.pm riga 58. Uso del valore non inizializzato $ msg in concatenazione (.) O stringa in /usr/local/share/perl/5.20.2/DBIx/Class/Exception.pm riga 68. DBIx :: Class :: Storage :: txn_commit (): Rifiuto di eseguire il commit senza una transazione avviata
Se rimuovo il comando di commit duplicato, funziona per il programma non Moose, ma il programma che utilizza Moose omette il commit e la voce creata non verrà scritta nel database.
Qualcuno conosce questi problemi?
Risposte
Dalla documentazione ditxn_do ,
ATTENZIONE: Se sei connesso con
AutoCommit => 0la transazione è considerata annidata, e dovrai comunque chiamare "txn_commit" per scrivere le tue modifiche quando appropriato. Ti consigliamo anche di connettertiauto_savepoint => 1per far funzionare il rollback parziale, se il driver di archiviazione per il tuo database lo supporta.
AutoCommit => 1Si consiglia di connettersi con .
Sospetto che tu stia usando AutoCommit => 0quando hai bisogno dell'extra txn_commit.
La risposta breve è: stai eseguendo il commit della transazione due volte. txn_doesegue automaticamente il commit quando si lascia il blocco quando non viene generata alcuna eccezione. Pubblica un esempio di codice che carica Moose e il log da DBIC_TRACE = 1 che mostra che non viene attivato alcun commit.