簡體   English   中英

在多個服務器上運行的 Rails 應用程序中,如何確保 rake 任務只運行一次?

[英]In a Rails app running on multiple servers, how can I make sure a rake task runs only once?

我有一個 Rails 應用程序在生產中的 2 個服務器上運行。

我有一個 rake 任務,它運行一些導入,然后向用戶發送電子郵件。 我現在收到 2 封電子郵件,因為有 2 台服務器。

為了避免這種情況,我嘗試創建一個表my_import_run

  1. 我的導入將檢查表中是否存在具有當前日期的記錄,僅當 NOT 導入將運行並發送電子郵件時。
  2. 發送電子郵件后,表中的所有記錄將被刪除,並添加一個只有當前日期的記錄

上述算法的實現如下所示:

def self.import(search_date = Date.current)
  if 0 == MyImportRun.count || !MyImportRun.where(:last_run => Date.today).any?
    # the code to run import job and send email goes here
    #
    #
    #
    #
    MyImportRun.delete_all
    MyImportRun.new(:last_run => Date.today)
    MyImportRun.save    
  end

但即使在執行上述代碼后,我仍然收到 2 封電子郵件 - 我不知道為什么。 我想知道兩個導入可能在完全相同的時間運行,因此它們都不會找到具有當前日期的記錄並運行導入,發送電子郵件並刪除所有記錄並添加具有當前日期的記錄。

有沒有一種干凈的方法來避免這種情況發生? 據我所知,rake 任務會自動導入到 Linux 中的 cron 作業中; 所以我不能只從一台服務器上刪除 rake 文件。

我確信必須有一種干凈的方法來避免這種重復。

如果您使用WheneverCapistrano該功能也可以用roles :在部署文件,您可以設置角色的列表:

server 'first-server', user: 'deployer', roles: %w{app db web sidekiq job}, primary: true
server 'second-server', user: 'deployer', roles: %w{app db web sidekiq job2}

schedule.rb

every 1.day, at: '5:00am', roles: [:job] do # this task will be run only on the first server
  rake "-s sitemap:refresh:no_ping"
end
every 1.day, at: '5:00am', roles: [:job2] do # this only on second
  rake "another_rake_task"
end

更多細節你可以找到這個

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM