問題
ZEO サーバーにアクセスするパッケージを使用すると、Celery ワーカーがタスクの実行でハングします。ただし、 内でサーバーに直接アクセスする場合は、tasks.py
まったく問題ありません。
バックグラウンド
ZODBファイルを読み書きするプログラムがあります。複数のユーザーがこのデータベースに同時にアクセスして変更できるようにしたいので、複数のプロセスとスレッド間で安全にするZEO サーバーでデータベースを管理します。プログラムのモジュール内でデータベースを定義します。
from ZEO import ClientStorage
from ZODB.DB import DB
addr = 'localhost', 8090
storage = ClientStorage.ClientStorage(addr, wait=False)
db = DB(storage)
SSCCE
私は明らかにもっと複雑な操作を試みていますが、ルート オブジェクトまたはその子のキーのみが必要であると仮定しましょう。このコンテキストで問題を作成できます。
dummy_package
上記のコードを使用して、モジュール とdatabases.py
、データベース アクセスを実行するための必要最小限のモジュールを作成します。
# main.py
def get_keys(dict_like):
return dict_like.keys()
でデータベース アクセスを試行しない場合dummy_package
、データベースをインポートしてルートに問題なくアクセスできます。
# tasks.py
from dummy_package import databases
@task()
def simple_task():
connection = databases.db.open()
keys = connection.root().keys()
connection.close(); databases.db.close()
return keys # Works perfectly
ただし、接続または子を渡そうとするとroot
、タスクが無期限にハングします。
@task()
def simple_task():
connection = databases.db.open()
root = connection.root()
ret = main.get_keys(root) # Hangs indefinitely
...
違いがある場合、これらの Celery タスクは Django によってアクセスされます。
質問
では、まず、ここで何が起こっているのでしょうか。この方法で ZEO サーバーにアクセスすることによって何らかの競合状態が発生することはありますか?
すべてのデータベースに Celery の責任でアクセスさせることもできますが、それでは醜いコードになってしまいます。さらに、スタンドアロン プログラムとして機能するプログラムの機能が損なわれます。Celery ワーカーによって呼び出されるルーチン内で ZEO と対話することはできませんか?