12

私は、delayed_job によって非同期的に処理されるようにマークされた関数を持っています。

class CapJobs
  def execute(params, id)
    begin
      unless Rails.env == "test"
        Capistrano::CLI.parse(params).execute!
      end
    rescue
      site = Site.find(id)
      site.records.create!(:date => DateTime.now, :action => "Task Failure: #{params[0]}", :type => :failure)    
      site.save
    ensure
      yield id
    end 
  end   
  handle_asynchronously :execute
end 

この関数を実行すると、ブロックを渡します。

 capjobs = CapJobs.new
 capjobs.execute(parameters, @site.id) do |id|
   asite = Site.find(id)
   asite.records.create!(:date => DateTime.now, :action => "Created", :type => :init)
   asite.status = "On Demo"
   asite.dev = true
   asite.save
 end

これは、delayed_job なしで実行すると正常に動作しますが、それを使用して実行すると、次のエラーが発生します。

2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] SitesHelper::CapJobs#execute_without_delay failed with LocalJumpError: no block given (yield) - 0 failed attempts
2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] PERMANENTLY removing SitesHelper::CapJobs#execute_without_delay because of 1 consecutive failures.
2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] 1 jobs processed at 0.0572 j/s, 1 failed ...

渡されたブロックを取得していないようです。これは正しい方法ではありませんか、それとも別の方法を見つける必要がありますか?

4

3 に答える 3

10

delayed_job は、ジョブをデータ ストア (ほとんどの場合、プライマリ データベース) に保存し、バックグラウンド プロセスでこのデータ ストアからジョブをロードして処理/実行することで機能します。

ジョブをデータベースに保存するには、delayed_job は、どのメソッドをどのオブジェクトに対してどの引数で呼び出すかを何らかの方法で保存する必要があります。これは、すべてを文字列にシリアライズすることによって行われます (delayed_job はそのためにyamlを使用します)。残念ながら、ブロックはシリアライズできません。そのため、バックグラウンド ワーカーはブロック引数を認識せず、ブロック引数なしでメソッドを呼び出します。これによりLocalJumpError、メソッドがブロックに譲ろうとしているときに発生します。

于 2012-08-13T15:52:43.673 に答える
2

これを行う方法を見つけました。ちょっとハッキーですが、うまく機能します。SerializableProc クラスの作成について説明しているこの記事を見つけました。これを関数に渡すと、すべてがうまく機能します。

于 2012-08-13T17:15:18.143 に答える
0

ほとんどの人は、これを抽象化の問題として扱います。

proc コードはおそらく実行ごとに変更されないため (vars を除く)、ブロック コードをクラスまたはインスタンス メソッドにする必要があります。executeそのメソッドの名前を渡し、メソッドで呼び出します。

@some_data = CapJobs.send( target_method )

またはおそらく-より良い-さらに

@some_data = DomainSpecificModel.send( target_method )

于 2012-09-17T15:13:08.313 に答える