【Rails6】Active Job + Sidekiqを動かしてみた

6 min read読了の目安(約5500字

Railsの非同期処理をActive Job + Sidekiqで実装したのでメモを残します。

※RailsアプリケーションはDocker環境で構築済みの前提です。環境構築はこちら
※Active Jobとバックエンドの比較はこちら

環境

  • Ruby 2.7.2
  • Rails 6.0.3.4
  • MySQL 8.0.20
  • Redis 6.0.9
  • Sidekiq 6.1.2
  • Docker version 19.03.13

1. Redisの導入

まずredisコンテナを用意します。
ポート番号はdocker-compose.override.ymlで指定していますが、下記で設定して問題ないと思います。

docker-compose.yml
version: '3.7'

services:
  db:
    image: mysql:8.0.20
    volumes:
      - mysql:/var/lib/mysql:delegated
    command: --default-authentication-plugin=mysql_native_password
    env_file: .env

  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    tty: true
    stdin_open: true
    env_file: .env
    depends_on:
      - db
      - chrome
      - redis
    volumes:
      - .:/app:cached
      - bundle:/usr/local/bundle:delegated
      - node_modules:/app/node_modules

  chrome:
    image: selenium/standalone-chrome:3.141.59
    volumes:
      - /dev/shm:/dev/shm

  redis:
    image: redis:6.0.9
    env_file: .env
    command: redis-server --appendonly yes
    volumes:
      - redis:/data

volumes:
  mysql:
  bundle:
  node_modules:
  redis:
docker-compose.override.yml
version: '3.7'

services:
  db:
    ports:
      - 3306:3306
  web:
    ports:
      - 3000:3000
  chrome:
    ports:
      - 4444:4444
  redis:
    ports:
      - 6379:6379

Redisの設定ファイルを追加します。
host名に注意してください。

config/redis.yml
default: &default
  db:
    sidekiq: 0
    # cache:   1
    # session: 2

development:
  <<: *default
  host: redis

test:
  <<: *default
  host: redis

2. Sidekiqの設定

まずはGemを追加します。

Gemfile
gem 'sidekiq'

bundle installを実行し、設定ファイルを追加します。
詳しくは、こちらを参照してください。

config/sidekiq.yml
:verbose: false
:max_retries: 1
:concurrency: 10
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:queues:
  - development_default

続いてSidekiqとRedisの接続情報も追加します。

config/initializers/sidekiq.rb
redis_config = YAML.load_file('config/redis.yml')[Rails.env]
redis_config['db'] = redis_config['db']['sidekiq']

Sidekiq.configure_server do |config|
  config.redis = {
    url: "redis://#{redis_config['host']}/#{redis_config['db']}"
  }
end

Sidekiq.configure_client do |config|
  config.redis = {
    url: "redis://#{redis_config['host']}/#{redis_config['db']}"
  }
end

ダッシュボードのルーティングも設定します。

config/routes.rb
require 'sidekiq/web'

Rails.application.routes.draw do
  mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq
end

3. Active Jobの設定

Active Jobで非同期処理を実装していきます。

config/application.rb
require "active_job/railtie"

module App
  class Application < Rails::Application
    config.active_job.queue_adapter = :sidekiq
    config.active_job.queue_name_prefix = Rails.env # これは任意
  end
end

4. ジョブの作成と動作確認

ようやくジョブを作成します。

rails g job sample
app/jobs/sample_job.rb
class SampleJob < ApplicationJob
  queue_as :default

  def perform
    puts '--------------------------------'
    puts '------------  Test  ------------'
    puts '--------------------------------'
  end
end

続いて動作確認を行います。
dockerコンテナを起動し、RailsとRedisが動いていることを確認します。
コンテナ内でsidekiqを起動します。

$ bundle exec sidekiq -C config/sidekiq.yml

2020-11-23T07:06:57.513Z pid=74 tid=9om INFO: Booting Sidekiq 6.1.2 with redis options {:url=>"redis://redis/0"}


               m,
               `$b
          .ss,  $$:         .,d$
          `$$P,d$P'    .,md$P"'
           ,$$$$$b/md$$$P^'
         .d$$$$$$/$$$P'
         $$^' `"/$$$'       ____  _     _      _    _
         $:     ,$$:       / ___|(_) __| | ___| | _(_) __ _
         `b     :$$        \___ \| |/ _` |/ _ \ |/ / |/ _` |
                $$:         ___) | | (_| |  __/   <| | (_| |
                $$         |____/|_|\__,_|\___|_|\_\_|\__, |
              .d$$                                       |_|


2020-11-23T07:06:57.938Z pid=74 tid=9om INFO: Booted Rails 6.0.3.4 application in development environment
2020-11-23T07:06:57.939Z pid=74 tid=9om INFO: Running in ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]
2020-11-23T07:06:57.939Z pid=74 tid=9om INFO: See LICENSE and the LGPL-3.0 for licensing details.
2020-11-23T07:06:57.939Z pid=74 tid=9om INFO: Upgrade to Sidekiq Pro for more features and support: https://sidekiq.org
2020-11-23T07:06:57.946Z pid=74 tid=9om INFO: Starting processing, hit Ctrl-C to stop

別タブのターミナルでRailsコンソールからSampleJobをキューイングしてみます。

$ rails c
Loading development environment (Rails 6.0.3.4)
> SampleJob.set(wait: 5.second).perform_later

Enqueued SampleJob (Job ID: fdcf5c60-3542-4b26-bfd2-9662ffafada9) to Sidekiq(development_default) at 2020-11-23 07:08:49 UTC
=> #<SampleJob:0x00005567e535e4c0
 @arguments=[],
 @exception_executions={},
 @executions=0,
 @job_id="fdcf5c60-3542-4b26-bfd2-9662ffafada9",
 @priority=nil,
 @provider_job_id="7c42f602bd499e75efecad26",
 @queue_name="development_default",
 @scheduled_at=1606115329.3860393>
>

キューイングすると先ほど起動したSidekiq側でジョブが実行されたことが確認できました。

2020-11-23T07:08:52.800Z pid=74 tid=b6y class=SampleJob jid=7c42f602bd499e75efecad26 INFO: start
--------------------------------
------------  Test  ------------
--------------------------------
2020-11-23T07:08:53.067Z pid=74 tid=b6y class=SampleJob jid=7c42f602bd499e75efecad26 elapsed=0.267 INFO: done