2016-10-22 20 views
0

Webとバックグラウンドワーカープロセスで構成されるアプリケーション用のPostgres(9.5)DBがあります。異なるPostgresセッションからのロックとロック解除

HTTPリクエストPOST /items/123/stepsを受け取った場合、Webアプリケーションはアイテム123に「ワークフローステップ」を実行して戻るためのバックグラウンドタスクをキューに入れます。アイテムは、目標は、バックグラウンドタスクは、アイテムのロックを解除するまでPOST /items/123/stepsに後続の要求が拒否されるように、何らかの方法で処理するための項目123をロックすることであるPostgresのitemsテーブル内の行に対応したID値123

と列を有しています123作業を完了した後。

同様に、GET /items/123への要求は、アイテム123がロックされていることを示す属性を返して、バックグラウンドタスクがアイテムをロック解除するまでUIが現在処理中のアイテムを表示できるようにする必要があります。

バックグラウンドタスクがそのキューから取得されるまでに遅延が生じる可能性があるため、バックグラウンドタスクが実行を開始するときにアイテム123をロックするのに十分ではありません。アイテム123は、バックグラウンドタスクが完了するまで最初のPOST Webリクエストからロックされたものとしてマークされ、バックグラウンドタスクが選択される前に入ってくるWebリクエストに対してロックされたアイテムとして表示されます。

可能であれば、これを達成するためにPostgresを使用したいと思います。しかし、私が見つけたのオプションが動作していないようです:トランザクションが終了したときに

  • Row locksは私のWebハンドラが戻ったときに発生する、解放されています。バックグラウンドタスクは、異なるトランザクションでその作業を実行します。だから私はアイテム123にSELECT FOR UPDATEを実行することはできません。
  • セッションレベルadvisory lockは、Webプロセスから取得した場合、Webプロセスとワーカープロセスをそれぞれ処理するため、ワーカープロセスからロックを解除できません独自のPostgresセッションを確立する。 itemslocked列を追加し、バックグラウンドタスクに戻っFALSEにし、WebエンドポイントでTRUEに設定し、:

私はアドホックロック機構を実装することでこの問題を回避することができます。それを行う標準的な方法が存在する場合は、私はむしろそれを行うだろう。

追加情報:これはPythonプロジェクトで、(Flask)Webアプリケーションと(Celery)バックグラウンドタスクの両方からPostgresにアクセスするためにSQLAlchemyを使用しています。私のために機能するこれらのツールで目標を達成するためのもう一つの実証済みの方法がある場合。

答えて

1

“回避策”のlockedを使用して実際には正しい解決策です。

あなたが正しく観察しているように、定期的な錠や助言はあなたの所見ではうまくいきません。

関連する問題