Sử dụng sidekiq cùng activeJob trong Rails 4.2.0
Bài đăng này đã không được cập nhật trong 9 năm
Giới thiệu
Một trong những điều thú vị trong Rails 4.2.0 đó là việc tích hợp sẵn gem ActiveJob vào. Điều này tạo cho chúng ta thêm một lựa chọn hết sức đơn giản và dễ dàng khi muốn tạo một background job với những gem trước đây như DelayedJob, Resque... Với bài viết này tôi sẽ hướng dẫn các bạn một cách đơn giản nhất để sử dụng Sidekiq kết hợp với ActiveJob để tạo ra một background job như mong muốn.
1 Cài đặt
ActiveJob chỉ được hỗ trợ từ Rails 4.2 trở đi nên trước tiên bạn hãy chắc chắn đã cài đặt phiên bản mới nhất của Rails. Thêm vào Gemfile
gem "rails", "4.2.0"
Tiếp theo đó bạn cài đặt đặt Sidekiq
, tiếp tục khai báo vào Gemfile
gem "sidekiq"
Chạy dòng lệnh bundle
Tạo config file config/sidekiq.yml
với nội dung
---
:concurrency: 25
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:queues:
- default
Config file trên để thông báo với Sidekiq
nơi lưu PID và log file. Thêm vào đó config cho Sidekiq
tạo ra 1 queue default
Ngoài cách nói trên bạn cũng có thể config theo nhiều cách khác nhau sao cho phù hợp với project của bạn nhất.
Chúng ta khởi động Sidekiq
bằng dòng lệnh :
$ sidekiq -C config/sidekiq.yml
Nếu Sidekiq
được khởi động thành công bạn sẽ thấy output dưới dạng :
2014-10-03T01:23:24.775Z 13918 TID-oxapc5ias INFO: See LICENSE and the LGPL-3.0 for licensing details.
2014-10-03T01:23:24.776Z 13918 TID-oxapc5ias INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org/pro
2014-10-03T01:23:24.776Z 13918 TID-oxapc5ias INFO: Starting processing, hit Ctrl-C to stop
2014-10-03T01:23:24.777Z 13918 TID-oxaphajos DEBUG: {:queues=>["default"], :labels=>[], :concurrency=>25, :require=>".", :environment=>nil, :timeout=>8, :error_handlers=>[#<Sidekiq::ExceptionHandler::Logger:0x007fe76b1cfcc8>], :lifecycle_events=>{:startup=>[], :quiet=>[], :shutdown=>[]}, :verbose=>true, :daemon=>false, :pidfile=>"./tmp/pids/sidekiq.pid", :logfile=>"./log/sidekiq.log", :strict=>false, :config_file=>"config/sidekiq.yml", :tag=>"demo_app"}
Để thoát Sidekiq
bạn ấn tổ hợp phím Ctrl-C.
Chúng ta cũng có thể chạy Sidekiq
trong daemon mode
bằng cách sửa vào file config/sidekiq.yml
:
---
:concurrency: 25
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:queues:
- default
:daemon: true
Giờ hãy chạy lại sidekiq
2 Tạo Job
Giả sử bạn muốn thực hiện import CSV ở background. Và đây là class của bạn :
class CsvImporter
attr_reader :filepath
def initialize(filepath)
@filepath = filepath
end
def run
puts "Prepare to import #{filepath} ..."
# some crunching code
puts "Import #{filepath} completed"
end
end
Giờ chúng ta config để sử dụng sidikiq
là người thực hiện chạy công việc của bạn dưới background
#config/initializers/active_job.rb
ActiveJob::Base.queue_adapter = :sidekiq
Theo quy ước bạn viết Job của bạn trong app/jobs
ví dụ:
# app/jobs/csv_import_job.rb
class CsvImportJob < ActiveJob::Base
queue_as :default
# we assume that we have a class CsvImporter to handle the import
def perform(filepath)
CsvImporter.new(filepath).run
end
end
Bạn có thể thấy ở trên có 2 phương thức đó là queue_as
và perform. Đó là 2 phương thức mặc định của theo chuẩn chung khi bạn tạo 1 ActiveJob class.
Như bạn đã biết sidekiq
hỗ trợ multiple queues, chúng ta có thể config các hàng đợi này trong các file config của sidekiq
. Ở ví dụ trên chúng ta khai báo CsvImportJob là default queue thông qua API queue_as
.
Phương thức perform
là nơi thực hiện logic xử lý công việc. Lưu ý là các đối số phải là kiểu String
, Integer
, Flat
, nil
, True
/ False
, Hash
, Array
hoặc GlobalID
.
3 Chạy Job
Chúng ta có thể khai báo với Rails thực hiện chạy Job ngay khi có thể với phương thức #perform_later
:
CsvImportJob.perform_later('/tmp/my_file.csv')
Bạn có thể kiểm tra xem Job của mình đã thực hiện thành công hay chưa trong log/development.log
. Nếu Job được chạy thành công bạn sẽ thấy:
[ActiveJob] Enqueued CsvImportJob (Job ID: 525b3f7b-adab-41de-afe7-bee229188501) to Sidekiq(csv) with arguments: "/tmp/my_file.csv"
Ngoài ra bạn cũng có thể đặt lịch cho Job của bạn thực hiện với phương thức #set
kết hợp với wait_until
CsvImportJob.set(wait_until: Date.tomorrow.noon).perform_later('/tmp/my_file.csv')
hoặc
CsvImportJob.set(wait: 2.week).perform_later('/tmp/my_file.csv')
Chú ý
Theo như cách làm ở trên ActiveJob
là nhiệm vụ quản lý hàng đợi cho các Job còn sidekiq
có nhiệm vụ thực hiện chạy các Job.
Như vậy bạn đã tạo ra 1 background job
một cách hết sức đơn giản
Chúc các bạn thành công !!!
All rights reserved