[英]Passing a Block to a delayed_job
我有一个标记为由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 ...
它似乎没有拿起传入的块。这不是正确的方法,或者我应该找到一个不同的方法?
delayed_job的工作原理是将作业保存到数据存储(通常是主数据库)中,然后在后台进程中将作业加载到此数据存储中,并在其中处理/执行。
要将作业保存到数据库中,delayed_job需要以某种方式保存使用什么参数调用哪个对象的方法。 这是通过将所有内容序列化为字符串来完成的(delayed_job使用yaml )。 不幸的是,块无法序列化。 所以后台工作者不知道块参数,并在没有它的情况下调用该方法。 当方法试图屈服于块时,这会导致LocalJumpError
。
我找到了一种方法。 它有点hacky但效果很好。 我发现这篇文章讨论了如何创建SerializableProc类。 如果我把它传递给函数,那么一切都很好。
大多数人会将此视为抽象问题。
proc代码可能不会从run-to-run(vars除外)改变,所以你应该将块代码变成类或实例方法。 传递该方法的名称,然后在execute
方法中调用它,如
@some_data = CapJobs.send( target_method )
或许甚至更好
@some_data = DomainSpecificModel.send( target_method )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.