[Rails] 排程使用 ActiveJob + Sidekiq + Sidekiq-cron
前言
Active Job 是rails官方內建的背景執行程序,有adapter可用來連接外部的Sidekiq、resque、delay job等 我個人認為語法滿簡潔的,而且如果以後想改resque或其他也滿好處理 這邊使用sidekiq來執行,並搭配Sidekiq-cron這個plugin來設定排程 並且會安裝Web UI來快速查看執行狀況
說明
sidekiq其實是一個服務,他還搭配了redis這個資料庫
當我們使用sidekiq建立一個排程,其實是建立在redis資料庫中, 如果有安裝sidekiq-corn的話,運作的排程也放在redis
這和我們一般使用whenever建立cron不一樣 whenever建立的cron是放在作業系統(Linux或mac)內建的crontab中,就不用另外啟動其他服務
但使用sidekiq,則一定要確保sidekiq及redis都有運作
前置作業
#####安裝Redis Redis官方網站
安裝 redis 資料庫 $ brew install redis
啟動 redis 資料庫 $ brew services start redis
若需要其他資訊可以輸入 $ brew info redis
#####安裝Sidekiq Sidekiq官方網站
gem 'sidekiq'
gem "sidekiq-cron", "~> 0.4.0"
$ bundle install
第一個Job
1. 新增一個 Active Job
$ rails generate job guests_cleanup
可以發現在 /job 中多了一個 guests_cleanup_job.rb 調整一下perform中輸出的文字
class GuestsCleanupJob < ActiveJob::Base
queue_as :default
def perform(*args)
puts 'hello Job!!!'
end
end
這樣我們就建好一個job了
可以在rails c
中
輸入 GuestsCleanupJob.perform_later
測試,他會把上執行
輸入 GuestsCleanupJob.set(wait_until: Date.tomorrow.noon).perform_later(record)
測試,他會等到明天中午執行
輸入 GuestsCleanupJob.set(wait: 1.week).perform_later(record)
測試,他會等一週後才執行
2. sidekiq
只要加入adapter是sidekiq即可
# [path] application.rb
class Application < Rails::Application
config.active_job.queue_adapter = :sidekiq
end
加入此行後,之後的原本執行job的指令(如: GuestsCleanupJob.perform_later
),就會丟給sidekiq去執行
記得sidekiq服務要啟動,需要執行 sidekiq
3. sidekiq web UI
加上即可
# [path] route.rb
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'
之後就可以在 http://xxxx/sidekiq 中看到所有job執行狀況
4. sidekiq-cron
sidekiq-corn web UI介面
加入 require 'sidekiq/cron/web'
即可 (要在sidekiq/web之後)
# [path] route.rb
require 'sidekiq/web'
require 'sidekiq/cron/web'
mount Sidekiq::Web => '/sidekiq'
官方提供好幾種設定排程方式,這邊介紹兩種:
(1) 直接新增 Sidekiq::Cron::Job.create( name: ‘Hard worker - every 5min’, cron: ‘*/5 * * * *’, class: ‘HardWorker’, active_job: true )
(2) YML ```yml config/schedule.yml my_first_job: cron: “*/5 * * * *” class: “HardWorker” queue: hard_worker active_job: true
second_job: cron: “*/30 * * * *” # 分 時 日 月 週 class: “HardWorker” # 需對應你的Job queue: hard_worker_long # 優先權設定,詳細請看官網說明 active_job: true # 因為我們使用active_job建立,請設為true args: hard: “stuff”
```rb
# [path] config/initializers/sidekiq.rb
schedule_file = "config/schedule.yml"
if File.exists?(schedule_file) && Sidekiq.server?
Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
end
另外如果要跑ActionMail的話,因為預設的queue是mailer 記得要加上sidekiq.yml設定mailers的queue (否則他只會跑default,你的mail就會被一直晾在queue中) ```yml sidekiq.yml — :concurrency: 1 :queues:
- default
- mailers ```
記得sidekiq要run
Reference
- http://rails.ruby.tw/active_job_basics.html
- https://github.com/kakas/Kaohsiung_Rails_Sidekiq_demo
留言