1

Wenn ich eine verzögerte transaktionale Aufgabe von einer Transaktionsfunktion aufrufen, kann f, f festschreiben, während die verzögerte Aufgabe fehlschlägt.App-Engine Verkettung verzögerte transaktionale Aufgaben

Wenn ich jedoch f über einen verzögerten Aufruf aufrufen, schlägt die aufrufende Funktion fehl.

Um repro, ich habe folgendes:

@ndb.transactional() 
def f(): 
    # modify datastore entity X 
    ... 
    x.put() 

class X(ndb.Model): 
    ... 
    def _post_put_hook(self, future) 
    deferred.defer(y, 
        _transactional=ndb.in_transaction()) 
def y(): 
    raise Exception() 

Als ich f nennen, die verschobene Aufgabe fehlschlägt, aber x.put() Commits.

ABER, wenn ich deferred.f aufrufen, schlägt x.put() fehl.

Antwort

0

Ich glaube, Sie haben missverstanden, was das _transactional optionale Argument in deferred.defer(y, _transactional=ndb.in_transaction()) tut. Es bedeutet nicht, dass die verzögerte y Ausführung in die gleiche Transaktion ausgeführt wird, in der deferred.defer() aufgerufen wurde, bedeutet es nur, dass die aufgeschobene Aufgabe in die Warteschlange gestellt wird, wenn die Transaktion erfolgreich ist.

Von google.appengine.ext.deferred.deferred module:

google.appengine.ext.deferred.deferred.defer (obj, * args, ** kwargs)

[...]

  • obj - Die abrufbare Ausführung. Siehe Modul Docstring für Einschränkungen. _countdown, _eta, _headers, _name, _target, _transaktional, _url, _retry_options, _queue: An die Taskwarteschlange übergeben - weitere Informationen finden Sie in der Dokumentation zur Taskwarteschlange.

Und von google.appengine.api.taskqueue.taskqueue module:

add (Aufgabe, Transaktions- = False)

[...]

  • Transaktions - Wenn True, Transaktionsaufgaben Wird zur Warteschlange hinzugefügt, kann aber erst nach dem Start ausgeführt oder geleast werden Die Transaktion ist erfolgreich. Wenn die Transaktion fehlschlägt, werden die Aufgaben aus der Warteschlange entfernt (und werden daher nie ausgeführt). Wenn False, sind die hinzugefügten Aufgaben sofort ausführbar; Der Erfolg einer umschließenden Transaktion oder Fehler wird ignoriert.

Die tatsächliche Ausführung der verschobene Aufgabe wird immer in einem anderen Transaktionskontext auf einen anderen Wunsch getan, als dem, in dem deferred.defer() genannt wurde. Aus diesem Grund kann Ihre verzögerte Aufgabe fehlschlagen, selbst wenn Ihre ursprüngliche Transaktion erfolgreich ist.