在config/application.rb
中,添加以下内容
config.autoload_paths += Dir["#{config.root}/app/jobs/**/"]
在 处创建一个新目录app/jobs/
。
创建一个app/jobs/api_job.rb
看起来像的文件
class ApiJob < Struct.new(:attr1, :attr2, :attr3)
attr_accessor :token
def initialize(*attrs)
self.token = self.class.token(attr1, attr2, attr3)
end
def display_name
self.class.token(attr1, attr2, attr3)
end
#
# Class methods
#
def self.token(attr1, attr2, attr3)
[name.parameterize, attr1.id, attr2.id, attr3.id].join("/")
end
def self.find_by_token(token)
Delayed::Job.where("handler like ?", "%token: #{token}%")
end
end
注意:您将替换attr1
, attr2
, 和attr3
您需要的任意数量的属性(如果有)传递给ApiJob
以执行排队的任务。稍后详细了解如何调用它
对于您排队的每个 API,get_and_create_or_update_users
您将创建另一个Job
. 例如,如果我有一些Facebook
api 模型,我可能有一个app/jobs/facebook_api_job.rb
看起来像的类
class FacebookApiJob < ApiJob
def perform
FacebookApi.new.get_and_create_or_update_users(attr1, attr2, attr3)
end
end
注意:在您的问题中,您没有将任何属性传递给get_and_create_or_update_users
. 我只是向您展示如果您需要将属性传递给它的作业,您将在哪里执行此操作。
最后,无论你在哪里refresh_users_list
定义,定义类似这个job_exists?
方法的东西
def job_exists?(tokens)
tokens = [tokens] if !tokens.is_a?(Array) # allows a String or Array of tokens to be passed
tokens.each do |token|
return true unless ApiJob.find_by_token(token).empty?
end
false
end
现在,在您的refresh_users_list
and 循环中,您可以构建新的令牌并调用job_exists?
以检查您是否为 API 排队作业。例如
# Build a token
def refresh_users_list
apis_array.each do |api|
token = ApiJob.token(attr1, attr2, attr3)
next if job_exists?(token)
api.myclass.new.delay.get_and_create_or_update_users
end
end
注意:我想再次指出,你不能只输入上面的代码并让它工作。您必须根据您的应用程序和您正在运行的工作对其进行定制。
为什么这么复杂?
根据我的研究,没有办法通过delayed_job
提供的内容来“标记”或唯一标识排队的工作。当然,每个工作都有一个独特的:id
属性。您可以将每个创建的作业的 ID 值存储在某个散列中
{
"FacebookApi": [1, 4, 12],
"TwitterApi": [3, 193, 44],
# ...
}
然后检查相应的哈希键的 ID,但我发现这个限制,并不总是足够的问题当您需要通过多个属性识别特定作业时,我们必须创建一种方法来查找这些作业(无需加载每个将作业放入内存并循环遍历它们以查看是否符合我们的标准)。
这是如何工作的?
extends 有一个Struct
属性。此标记基于传递的属性( , , ) ,并在实例化新扩展类时构建。ApiJob
:token
attr1
attr2
attr3
ApiJob
类方法只是根据使用相同类方法构建的令牌find_by_token
在队列中搜索作业的字符串表示以查找匹配项。delayed_job
token