メインの Django アプリケーション プロセスで Celery タスクの結果にアクセスするにはどうすればよいですか? または、別のプロセスから既存のソケット接続に公開するにはどうすればよいですか?
ユーザーがスコアを受け取るアプリケーションがあります。スコアが記録されると、計算が行われ (目標への進捗状況など)、それらの計算に基づいて、関心のあるユーザーに通知が送信されます。計算には 30 秒以上かかる場合があるため、UI の遅延を避けるために、これらの操作は、Score モデルの post_save シグナルによって呼び出される Celery タスクを介してバックグラウンド プロセスで実行されます。
私の Nofication モデルの post_save シグナルが、サブスクライブしたクライアントにメッセージを発行するのが理想的です (私は gevent-socketio のラッパーである django-socketio を使用しています)。これは簡単に思えます...
- スコアを作成する
- バックグラウンド プロセスで新しい Score インスタンスに対していくつかの計算を行う
- これらの計算に基づいて、通知を作成します
- 通知の保存時に、インスタンスを取得し、ソケット接続を介してサブスクライブしたクライアントに公開します
ただし、次のことを試した後、これが可能かどうかわかりません。
gevent の SocketIOServer インスタンスをタスクによって呼び出されたコールバック メソッドに渡しますが、これには渡されたオブジェクトをピクルする必要があり、これは不可能です。
ソケットの session_id (Django の session_id とは異なります) を memchache に格納し、それを Celery タスク プロセスで取得します。
Redis pubsub を使用するため、バックグラウンド プロセスで作成されたモデルの post_save シグナルによって呼び出されるメソッドは、単純に Redis チャネルに発行できますが、(ソケット接続にアクセスできる) メイン アプリケーション プロセスでチャット チャネルをリッスンすると、アプリケーションの残りの部分がブロックされます。
また、Redis クライアントごとに新しいスレッドを生成しようとしました。これは、ソケット サブスクライバーごとに作成されます。私が知る限り、これには新しいgevent.greenlets.Greenletを生成する必要があり、geventは複数のスレッドで使用できません
確かにこれは解決済みの問題です。私は何が欠けていますか?