2016-10-22 6 views
0

Ich habe eine Postgres (9.5) DB für eine Anwendung, die aus Web- und Hintergrund-Worker-Prozessen besteht.Sperren und Entsperren von verschiedenen Postgres-Sitzungen

Wenn wir die HTTP-Anforderung POST /items/123/steps empfangen, wird die Webanwendung eine Hintergrundaufgabe in die Warteschlange stellen, um einen "Workflow-Schritt" für Element 123 auszuführen und zurückzukehren. Der Artikel entspricht eine Zeile in der Postgres items Tabelle und hat eine Spalte mit dem ID-Wert 123

Ziel ist es, irgendwie Sperre Artikel 123 für die Verarbeitung, so dass nachfolgende Anforderungen an POST /items/123/steps werden, bis das Aufgabenelement entriegelt Hintergrunds zurück 123 nach Abschluss seiner Arbeit.

In ähnlicher Weise müssen Anforderungen an GET /items/123 ein Attribut zurückgeben, das angibt, dass Element 123 gesperrt ist, so dass die UI das Element als gerade verarbeitet anzeigen kann, bis die Hintergrundaufgabe es entsperrt.

Da es möglicherweise eine Verzögerung gibt, bis die Hintergrundaufgabe aus der Warteschlange übernommen wird, ist es für die Hintergrundaufgabe nicht ausreichend, Element 123 zu sperren, wenn es gestartet wird. Ich möchte, dass Artikel 123 von der ursprünglichen Webanfrage POST als gesperrt markiert wird, bis die Hintergrundaufgabe abgeschlossen ist, sodass das Element als für alle Webanforderungen gesperrt angezeigt wird, die vor der Abholung der Hintergrundaufgabe eingehen.

Wenn möglich, möchte ich Postgres verwenden, um dies zu erreichen. Allerdings sind die Optionen, die ich gefunden habe, nicht zu funktionieren scheint:

  • Row locks freigegeben werden, wenn die Transaktion endet, die, wenn sie zurückkehrt meine Web-Handler auftritt. Die Hintergrundaufgabe führt ihre Arbeit in verschiedenen Transaktionen aus. So kann ich nicht ein SELECT FOR UPDATE auf Element 123.
  • Eine Sitzungsebene advisory lock kommt näher, außer dass, wenn ich es aus dem Web-Prozess ich kann nicht aus dem Worker-Prozess entsperren, da das Web und Worker jeweils verarbeitet eine eigene Postgres-Sitzung einrichten.

Ich kann durch die Implementierung eines Ad-hoc-Verriegelungsmechanismus dieses Problem umgehen: Fügen Sie eine locked Spalte items und es TRUE im Web Endpunkt gesetzt und dann wieder auf FALSE im Hintergrund Aufgabe. Wenn es einen standardmäßigen Weg gibt, dies zu tun, würde ich das lieber tun.

Zusätzliche Informationen: Es ist ein Python-Projekt und ich benutze SQLAlchemy, um auf Postgres sowohl von der (Flask) Web App als auch von (Sellerie) Hintergrundaufgaben zuzugreifen. Wenn es einen anderen bewährten Weg gibt, um das Ziel mit diesen Tools zu erreichen, die für mich arbeiten.

Antwort

1

Ihre “ Problemumgehung ” der Verwendung einer locked Spalte ist eigentlich die richtige Lösung.

Wie Sie richtig sehen, funktionieren weder normale Sperren noch Advisory gut in Ihrer Situation.

Verwandte Themen