9

投稿付きのブログアプリケーションがあるとしましょう。投稿を作成した後、いくつかのバックグラウンド操作を処理するワーカーが作成されます。私の場合、投稿フォームを送信した後、何らかの読み込みメッセージ(gifローダーなど)を表示したいのですが、ワーカーが終了したら、読み込みメッセージを非表示にして、ワーカーから提供されたデータを表示したいと思います。私の質問は、ワーカーが仕事を終えたことを伝え、ユーザーのフロントエンドに表示するための最良の方法は何ですか。ワーカーのコールバックは次のようになります

def worker_finish
  #message the user
end
4

1 に答える 1

13

バックグラウンドワーカーがいるという点を見逃しているのではないかと思います。基本的に、あなたがやろうとしているのは自滅です。-ユーザーがフォームを送信し、コントローラーでジョブをキューに入れて、ワーカーが開始と終了の両方を実行するのをユーザーに待たせる場合、コントローラーが単独で実行できることを正確に実行しただけでなく、プロセスがはるかに複雑になりました(このタイプの機能は、resqueまたはsidekiqのいずれにも組み込まれていません)。

キューによって処理されるジョブをオフロードするとき、クライアントにすぐに応答を返したい、つまり

class PostsController < ApplicationController
  def create
    @post = Post.create(params[:post])
    BackgroundBlogOperation.enque(@post.id)
    respond_with(@post)
  end
end

次に、BackgroundBlogOperationクラスがキューに入れられ、ワーカーが通過して作業できるようになります。終了後にBackgroundBlogOperationワーカーに何か他のことをさせる必要がある場合は、そうすることができますが、それはジョブ自体の中で行われる必要があります。そうすれば、ワーカーがその責任を負うことができます。

ページをリロードせずに、投稿の作成後にスピナーを表示および非表示にしようとしている場合は、送信ボタンをクリックする前にjavascriptスピナーを表示し、リクエストタイプがjsであることを確認してください(フォームに:remote => trueを追加) )。次に、次のようなJavaScriptビュー応答を作成します。

class PostsController < ApplicationController
  respond_to :js, :only => [:create]
  def create
    @post = Post.create(params[:post])
    BackgroundBlogOperation.enque(@post.id)
    respond_with(@post)
  end
end

また、create.js.erbは、投稿の作成などよりも複雑な場合は、バックグラウンドで実行していることはすべてキューに入れられたことを通知するメッセージを追加することもできます。

$("#spinner").hide();

今-あなたが最初に求めていたものは何の目的にも役立ちませんが(ジョブの完了時にスピナーを表示および非表示にするには、コントローラーがアクションを完了するのを待つ必要があるため)-クライアントにジョブを表示する状況があります処理が終了していると便利です。

まず、バックグラウンド処理が実際に役立つシナリオを定義しましょう。クリックすると外部APIからデータを取得するボタンがあり、外部サイトからデータを取得した後、応答に基づいてデータベース操作を実行しているとします。これは、バックグラウンドプロセスを使用する場合の良い例です。基本的に、コントローラーでは次のようなことを行います。

class ApiController < ApplicationController
  respond_to :js, :only => [:create]

  def sync_tweets
    TwitterApiJob.enque(current_user.twitter_username)
    respond_with(message: 'Syncing Tweets')
  end

end

ツイートの同期が終了したことをユーザーに通知するのは少し複雑で、3つの基本的なオプションがあります。

1)電子メールでユーザーに通知します(通常は最悪のオプションimo)2)何らかのhtml5またはwebsocket対応のrailsサーバーを使用してrailsを実行し、websocketを介してクライアントにプッシュを送信します。この応答の範囲外です。オプションを確認したい場合は、GoogleRailsWebSocketプッシュ。3)ほとんどの場合のIMOの最適なオプション、あらゆる種類のユーザー通知を処理する通知モデルを作成し、作業が完了したら、次のようなことを行います。

Notification.create(:user_id => user.id, :message => 'Sync has finished', type => 'sync_complete')

次に、ヘッダーツールバーなどでユーザーが要求する次のページで、ユーザーに未読の通知があることを通知し、ユーザーにクリックするように警告します。

---また、あなたの投稿で、resqueを使用しているとおっしゃっていたと思います。私はresqueを試しましたが、それはまともでしたが、本番環境でのデバッグには複雑すぎて、クレイジーなメモリを使用していました-まだ行っていない場合は、sidekiqをチェックすることをお勧めします。redisも使用しますが、使用するよりもはるかに高速ですスレッド:

https://github.com/mperham/sidekiq

それははるかに速く、きれいで、セットアップが簡単です、imho。

于 2012-11-15T06:30:52.957 に答える