Una transazione è un'operazione o un insieme di operazioni che è garantito che siano atomiche, il che significa che le transazioni non vengono mai applicate parzialmente. Vengono applicate tutte le operazioni nella transazione o nessuna. Le transazioni hanno una durata massima di 60 secondi con un periodo di scadenza di inattività di 10 secondi dopo 30 secondi.
Utilizzando l'API asincrona NDB,
un'applicazione può gestire più
transazioni contemporaneamente se sono indipendenti.
L'API sincrona offre un'API semplificata che utilizza il decoratore
@ndb.transactional()
.
La funzione decorata viene eseguita nel contesto della transazione.
Se la transazione "entra in conflitto" con un'altra, non va a buon fine; NDB ritenta automaticamente
alcune volte le transazioni non riuscite.
La funzione può essere chiamata più volte se la transazione
viene ritentata. Esiste un limite (3 per impostazione predefinita) al numero di tentativi
eseguiti; se la transazione non va ancora a buon fine, NDB
genera TransactionFailedError
. Puoi modificare il numero di tentativi
passando retries=N
al
decoratore transactional()
.
Un conteggio dei tentativi pari a 0 indica che la transazione
viene tentata una volta, ma non viene ritentata in caso di errore; un conteggio dei tentativi pari a
N indica che la transazione può essere tentata un totale di
N+1 volte. Esempio:
Nelle transazioni sono consentite solo le query di antenati. Per impostazione predefinita, una transazione può funzionare solo con le entità dello stesso gruppo di entità (entità le cui chiavi hanno lo stesso "antenato").
Puoi specificare transazioni cross-group ("XG") (che consentono fino a 25 gruppi di entità) passando xg=True
:
Le transazioni tra gruppi operano su più gruppi di entità e si comportano come le transazioni di un singolo gruppo, ma non hanno esito negativo se il codice tenta di aggiornare le entità di più di un gruppo di entità.
Se la funzione genera un'eccezione,
la transazione viene interrotta immediatamente e NDB genera di nuovo l'eccezione
in modo che il codice chiamante la visualizzi.
Puoi forzare l'interruzione silenziosa di una transazione generando l'eccezione
ndb.Rollback
(la chiamata di funzione restituisce
None
in questo caso). Non esiste un meccanismo per forzare un nuovo tentativo.
Potresti avere una funzione che non vuoi sempre
eseguire in una transazione. Anziché decorare una funzione di questo tipo
con @ndb.transactional
, passala come funzione di callback
a ndb.transaction()
Per verificare se un codice viene eseguito all'interno di una transazione,
utilizza la funzione
in_transaction()
.
Puoi specificare il comportamento di una funzione "transazionale" se viene richiamata
da un codice già presente in una transazione. Il decoratore
@ndb.non_transactional
specifica che una funzione
non deve essere eseguita in una transazione; se chiamata in una transazione, viene eseguita
al di fuori della transazione. Il decoratore @ndb.transactional
e la funzione ndb.transaction
accettano un
argomento di parola chiave propagation
. Ad esempio, se una funzione
deve avviare una nuova transazione indipendente, decorala nel seguente modo:
I tipi di propagazione sono elencati insieme alle altre Opzioni di contesto e Opzioni di transazione
Il comportamento delle transazioni e quello di memorizzazione nella cache di NDB possono combinarsi per creare confusione se non sai cosa sta succedendo. Se modifichi un'entità all'interno di una transazione, ma non hai ancora eseguito il commit della transazione, la cache di contesto di NDB contiene il valore modificato, ma il datastore sottostante contiene ancora il valore non modificato.
Accodamento delle attività transazionali
Puoi mettere in coda un'attività nell'ambito di una transazione Datastore, in modo che l'attività venga messa in coda solo se la transazione viene eseguita correttamente. Se il commit della transazione non viene eseguito, l'attività non viene inserita nella coda. Se viene eseguito il commit della transazione, l'attività viene messa in coda. Una volta accodata, l'attività non verrà eseguita immediatamente, pertanto non è atomica con la transazione. Tuttavia, una volta accodata, l'attività verrà ritentata finché non va a buon fine. Ciò vale per qualsiasi attività accodata durante una funzione decorata.
Le attività transazionali sono utili perché ti consentono di combinare azioni non Datastore a una transazione che dipende dalla riuscita della transazione (ad esempio, l'invio di un'email per confermare un acquisto). Puoi anche collegare le azioni Datastore alla transazione, ad esempio per eseguire il commit delle modifiche ai gruppi di entità al di fuori della transazione se e solo se la transazione ha esito positivo.
Un'applicazione non può inserire più di cinque attività transazionali nelle code di attività durante una singola transazione. Le attività transazionali non devono avere nomi specificati dall'utente.