将块传递给延迟作业

Posted

技术标签:

【中文标题】将块传递给延迟作业【英文标题】:Passing a Block to a delayed_job 【发布时间】:2012-08-09 16:25:32 【问题描述】:

我有一个标记为由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 ...

似乎没有拾取传入的块。这不是这样做的正确方法还是我应该找到其他方法?

【问题讨论】:

【参考方案1】:

delayed_job 的工作原理是将您的作业保存到数据存储(通常是您的主数据库)中,然后将作业从该数据存储中加载到后台进程中,并在其中处理/执行。

要将作业保存到数据库中,delayed_job 需要以某种方式保存使用什么参数调用哪个对象的方法。这是通过将所有内容序列化为字符串来完成的(delayed_job 为此使用 yaml)。不幸的是,块不能被序列化。所以后台工作人员不知道 block 参数并在没有它的情况下调用方法。当方法试图让步到块时,这会导致LocalJumpError

【讨论】:

【参考方案2】:

我找到了一种方法。这有点hacky,但效果很好。我发现this article 谈到了创建一个 SerializableProc 类。如果我将它传递给函数,那么一切都会很好。

【讨论】:

【参考方案3】:

大多数人会将此视为抽象问题。

proc 代码可能不会从运行到运行(vars 除外)发生变化,因此您应该将块代码变成类或实例方法。传递该方法的名称,然后在您的 execute 方法中调用它,例如

@some_data = CapJobs.send( target_method )

或者甚至更好

@some_data = DomainSpecificModel.send( target_method )

【讨论】:

以上是关于将块传递给延迟作业的主要内容,如果未能解决你的问题,请参考以下文章

将块传递给方法传递给Ruby中的另一个方法

如何从java将数据库连接传递给Kettle作业

如何将值传递给 Gitlab CI 作业

如何将AWS实例的详细信息传递给jenkins作业,以便该作业在实例中ssh和执行

将多个顺序 HBase 查询的结果传递给 Mapreduce 作业

如何将 JobParameters 传递给 Spring Cloud Task 启动的批处理作业?