4

Ich traf diese Ergebnis kann nicht zweimal festgelegt werden Laufzeitfehler auf GAE Ndb Async-Abfragen bei ndb.Future.wait_all(futures) auf eine Reihe von asynchronen Abfragen.GAE NDB "Ergebnis kann nicht zweimal eingestellt werden" Fehler

Etwas wie folgt aus:

futures = [] 
for item in items: 
    item._future_get = MyEntity.query(...).get_async() 
    futures.append(item._future_get) 

ndb.Future.wait_all(futures) 
# ... 

Es ist auf der wait_all mit Ergebnis ausfällt kann nicht eingestellt zweimal wird

Diese Fehlermeldung nirgendwo auf SO erwähnt. Google hat 2-3 Erwähnungen davon aus dem Jahr 2011 und ohne klare Erklärung.

Weitere Informationen:

Artikel sind ndb Einheiten aus einer früheren holen. Aber sie sind hier nicht wirklich wichtig (zumindest denke ich), da die Abfrage auf MyEntity durchgeführt wird. Ich bin es gewohnt, auf diese Weise Futures an das Objekt anzuhängen, auf das sie sich beziehen, so dass es leichter ist, zu sortieren, wenn alle fertig sind.

Der Stack-Trace:

File "/home/my_project/app/main/admin/my_module.py", line 166, in admin_base_cleanup_details ndb.Future.wait_all(futures) 
    File "/usr/lib/python2.7/google_appengine/google/appengine/ext/ndb/tasklets.py", line 350, in wait_all ev.run1() 
    File "/usr/lib/python2.7/google_appengine/google/appengine/ext/ndb/eventloop.py", line 235, in run1 delay = self.run0() 
    File "/usr/lib/python2.7/google_appengine/google/appengine/ext/ndb/eventloop.py", line 197, in run0 callback(*args, **kwds) 
INFO  2016-04-26 08:40:04,152 module.py:808] default: "GET /admin/cleanup/details?mode=status HTTP/1.1" 500 - 
    File "/usr/lib/python2.7/google_appengine/google/appengine/ext/ndb/tasklets.py", line 475, in _on_future_completion self._help_tasklet_along(ns, ds_conn, gen, val) 
    File "/usr/lib/python2.7/google_appengine/google/appengine/ext/ndb/tasklets.py", line 386, in _help_tasklet_along self.set_result(result) 
    File "/usr/lib/python2.7/google_appengine/google/appengine/ext/ndb/tasklets.py", line 265, in set_result 
    raise RuntimeError('Result cannot be set twice.') 
RuntimeError: Result cannot be set twice. 

Einige weitere Präzisierungen:

  • Ja, es ist auf GAE passieren sowie auf lokale dev.

  • Nein, es scheitert nicht jedes Mal, aber oft genug.

Ich fand, es hat mit Nebenläufigkeit von einem anderen Thread zu tun. Die Webseite startete 2 Anfragen über Ajax-Anrufe: eine für eine Aktualisierungsabfrage mit einigen asynchronen Anrufen, die einige Sekunden dauern würden, und eine andere wie eine periodische Statusaktualisierung, schneller aber auch mit asynchronen Anrufen. Letzteres ist nicht immer, aber sehr oft gescheitert. Seitdem habe ich es vermieden, die beiden Anfragen zu überlappen, und es hörte auf, zu versagen. Es scheint immer noch ein Fehler zu sein, da überlappende Anfragen nicht verboten sind.

+0

Sie erwähnen nicht, was 'item' nore ist die Linie, die die Ausnahme bekommt, könnte so _future_get eine modifizierbare Attribut und Element in Element dupliziert werden? –

+0

Sie sollten den Stack-Trace und ein bisschen mehr Informationen darüber, was ein 'Element' ist, hinzufügen. –

+0

@Tim Ich habe mehr Informationen zur ersten Frage hinzugefügt. – patb

Antwort

1

Sie verwenden get_async(), die "asynchron das erste Abfrageergebnis zurückgibt", während Sie wahrscheinlich fetch_async() verwenden sollten, um eine Zukunft zu erhalten.

https://cloud.google.com/appengine/docs/python/ndb/queryclass#Query_get_async

+0

Ich glaube, get_async() _gibt ein future_ zurück, obwohl es wahr ist, dass die Dokumentation, auf die Sie sich beziehen, das nicht explizit angibt. Wie sonst wäre es asynchron, wenn es nicht eine Zukunft, sondern eine Entität zurückgeben würde? – patb

+0

Sie haben Recht. ndb.get_async() gibt tatsächlich eine Zukunft zurück. Was Sie als Problemquelle beschreiben, ist ziemlich interessant. Vielleicht könnte ein Blick in die Tasklets eine konkretere Lösung bieten, ohne dass überlappende Anfragen vermieden werden müssen. –

Verwandte Themen