Transazioni Perl DBIx :: Class con commit mancante

Sep 29 2020

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

1 ikegami Sep 28 2020 at 23:39

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 connetterti auto_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.

AlexanderHartmaier Sep 30 2020 at 03:23

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.