2016-04-08 3 views
1

Wir laden eine Liste von E-Mail aus der Datei sein, während eine große Anzahl von Datenspeicherentität gleichzeitig für jede E-Mail-Adresse und bekam gelegentliche Fehler in Form setzen:gruppenübergreifende Transaktion muß explizit angegeben Ausnahme auf get_or_insert

BadRequestError: cross-group transaction need to be explicitly specified, see TransactionOptions.Builder.withXG 

der Python-Fehler Methodenaufruf:

EmailObj.get_or_insert(key_name=email, source=source, reason=reason) 

wo E-Mail die Adresse String und Quelle und Grund ist StringProperties sind.

Frage: Wie kann der get_or_insert-Aufruf eine Transaktion für ein einfaches Datenspeichermodell (2 String-Eigenschaften) starten und Entitäten von verschiedenen Gruppen einbeziehen? Ich erwarte, dass die obige Methode entweder das vorhandene Objekt lesen soll, das dem gegebenen Schlüssel entspricht, oder die neue Entität speichern soll.

+0

Haben Sie sehen http://stackoverflow.com/questions/15776823/cross -group-transaction-error-mit-nur-ein-entity? – snakecharmerb

+0

Ja, ich habe mir die Fragen zu diesem Fehler angesehen. Die Antworten sind hauptsächlich handwaving über den fehlenden Elternparameter, aber ich habe noch eine klare Antwort sehen, die erklärt, welche Gruppen in dieser speziellen Transaktion beteiligt sind. Der Fehler scheint zu implizieren, dass mindestens zwei Entitäten versucht wurden, geändert zu werden. – Marcel

Antwort

1

Hinweis: Ich weiß nicht, die genaue interne Implementierung, dies nur eine Theorie ist ...

Da Sie nicht ein Elternteil angegeben haben, dann gibt es keine Einheit Gruppe, die „gesperrt“ werden könnte/etabliert von Anfang an als die Gruppe, auf die die Transaktion beschränkt wäre.

Der Vorgang get_or_insert würde normalerweise eine Prüfung sein, ob die Entität mit diesem Schlüsselnamen existiert, und wenn nicht, dann erstellen Sie eine neue Entität. Ohne ein Elternteil wäre diese neue Entität in ihrer eigenen Gruppe, nennen wir sie new_group.

Jetzt, um die Transaktion abzuschließen, die automatisch mit get_or_insert verbunden ist, müsste eine Konfliktprüfung durchgeführt werden. Der Konflikt würde bedeuten, dass eine Entität mit demselben Schlüsselnamen durch eine der konkurrierenden Aufgaben erstellt wurde (nach unserer Prüfung, dass eine solche Entität existiert, aber vor unserem Transaktionsende), welche Entität auch ihre eigene andere Gruppe haben würde other_group.

Diese Konfliktprüfung, nur in dem Fall, in dem der Konflikt real ist, würde effektiv sowohl auf new_group als auch auf other_group zugreifen und die Ausnahme verursachen.

Durch die Angabe eines Elternteils existiert das Problem nicht, da sowohl new_group als auch other_group tatsächlich die gleiche Gruppe sind - die Elterngruppe. Die get_or_insert Transaktion wäre auf diese Gruppe beschränkt.

Die Theorie überprüft werden kann, glaube ich, auch in der Produktion (die Fehler eigentlich harmlos sind, wenn die Theorie richtig ist - die Adressen nach allen Duplikaten)

Erster Schritt wäre, um zu bestätigen, dass die Vorkommen verwendet sind an die same E-Mail-Adresse wird zweimal in kurzer Zeit eingefügt - concurently.

Wrap in versuchen/mit Ausnahme der Ausnahme und protokollieren Sie die entsprechende E-Mail-Adresse, dann überprüfen Sie es gegen die Eingabedateien - sie sollten Duplikate sein und ich stelle ziemlich nahe beieinander in der Datei.

Dann könnten Sie diese Bedingung erzwingen - absichtlich doppelte Adressen alle 5-10 E-Mails einfügen (oder eine andere Rate, die Sie für relevant halten).

Je nachdem, wie die App tatsächlich implementiert ist, können Sie die Duplikate in die Eingabedateien einfügen oder doppelte Aufgaben zweimal erstellen oder in die Warteschlange stellen oder einfach die get_or_insert aufrufen (nicht sicher, ob die letzte wirksam wird) Genug, wie es auf dem gleichen Thread/Instanz passieren kann). dich einzuloggen oder halten schließlich Spur der injizierten duplizierten Adressen

Das Auftreten Rate der Ausnahme sollte jetzt erhöhen, potenziell proportional mit der doppelten Einbaurate gezwungen. Die meisten, wenn nicht alle der entsprechenden protokollierten Adressen sollten mit den verfolgten Duplikaten übereinstimmen, die injiziert werden.

Wenn Sie soweit sind die doppelten Einträge als Trigger bestätigt. Was noch zu bestätigen wäre, wären die verschiedenen Entitätsgruppen für die gleiche E-Mail-Adresse - ich kann mir nicht vorstellen, das genau zu überprüfen, aber ich kann mir auch keine andere Gruppe vorstellen, die sich auf doppelte E-Mail-Adressen bezieht.

Anyways, fügen Sie einfach xg=True in die get_or_insert Anrufe context options und, wenn meine Theorie richtig ist, die Fehler sollte dissapear :)

+0

Danke, es klingt plausibel. Früher wurde heute ein Vorschlag gemacht, dass die get_or_insert einer bestehenden Transaktion beigetreten sein könnte, aber ich entschied das später, indem wir den Aufruf get_or_insert mit try/except und logging db.is_in_transaction() umgaben, was für alle Fälle falsch war Nur die Transaktion im Spiel ist von get_or_insert down. Das lässt nur zwei Entitäten (man würde denken). – Marcel

+0

Die Verwendung von XG löste es (musste die Funktion get_or_insert in eine Version get_or_insert_xp kopieren, die das Flag xg = True übergibt). Ich denke, wir müssen einfach leben, ohne genau zu wissen, was in diesem Szenario unter der Decke passiert. – Marcel