0

Sử dụng sidekiq cùng activeJob trong Rails 4.2.0

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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí