2012-12-12 15 views
0

我有一個這樣的方法,通過數組去發現不同的API,並啓動delayed_job實例發現這樣每個API檢查特定作業的存在。的delayed_job:如何根據觸發方法

def refresh_users_list 
    apis_array.each do |api| 
    api.myclass.new.delay.get_and_create_or_update_users 
    end 
end 

我有一個after_filter上​​控制器來觸發這種方法。這是創造許多就業機會被觸發,這將最終導致在Heroku too many connections問題。

我不知道是否有一種方法可以讓我檢查作業的數據庫由每個API,數組迭代的存在。這將非常有用,所以如果該API未在特定時間更新,我只能觸發特定刷新。

任何想法如何做到這一點?

回答

1
  1. config/application.rb,添加以下

    config.autoload_paths += Dir["#{config.root}/app/jobs/**/"] 
    
  2. app/jobs/創建一個新的目錄。

  3. 創建於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 
    

    注:您將取代attr1attr2,並attr3你需要的任何屬性的數量(如果有的話)傳遞給ApiJob執行排隊的任務。更多關於如何在一瞬間致電

  4. 對於您的每個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和循環中,你可以建立新的令牌,並呼籲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屬性。您可能店在一些哈希地方

{ 
    "FacebookApi": [1, 4, 12], 
    "TwitterApi": [3, 193, 44], 
    # ... 
} 

,然後選中相應的哈希鍵的ID爲每個創建的作業ID值,但我覺得這個限制,而且並不總是足夠的問題,當你需要我們必須創建一種方法來找到這些作業沒有加載到內存中的每項工作,並循環查看它們是否符合我們的標準)

這是如何工作的?

ApiJob擴展的Struct具有:token屬性。該令牌基於通過attr1,attr2,attr2,attr3傳遞的屬性,並且在擴展ApiJob的新類被實例化時建立。

find_by_token類方法簡單地搜索在delayed_job隊列基礎上使用相同token類方法建立了一個記號匹配的作業的字符串表示。

+0

+1爲完整答案。你有沒有檢查過https://github.com/collectiveidea/delayed_job#named-queues? – Martin

+0

是的,儘管爲了我的需要,我會有數百個隊列,這似乎不切實際。 – deefour