4
2

More than 1 year has passed since last update.

Rails, Sidekiq, RedisをDockerでセットアップし、指定した時間にジョブを実行する

Last updated at Posted at 2023-07-16

はじめに

この記事では、Dockerを使用してRails、Sidekiq、Redisをセットアップし、指定した時間にジョブを実行する方法を紹介する。今回は、ユーザーにリマインダーメールを送信する機能を例とする。

Sidekiqとは

SidekiqはRubyのバックグラウンドジョブ処理ライブラリで、非同期処理を行うために使用される。Redisをバックエンドとして作成したジョブを管理する。

非同期処理とは

プログラムが複数のタスクを並行して実行すること。重い処理や時間のかかる処理をバックグラウンドで行うことでパフォーマンスを向上させることができる。
メールの送信やデータのバッチ処理など、時間のかかるタスクを非同期に行うことが一般的。

DockerとDocker Composeの設定

まず、DockerとDocker Composeを使用して、Rails、MySQL、Redis、Sidekiqの各サービスをセットアップをする。以下のDockerfileとdocker-compose.ymlをプロジェクトのルートディレクトリに作成する。

FROM ruby:3.1
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
apt-get install -y nodejs
ENV TZ=UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN mkdir /VehicleMinders
WORKDIR /VehicleMinders
COPY Gemfile /VehicleMinders/Gemfile
COPY Gemfile.lock /VehicleMinders/Gemfile.lock
RUN bundle install
COPY . /VehicleMinders

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]
docker-compose.yml
version: '3'
services:
  db:
    platform: linux/amd64
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql-data:/var/lib/mysql
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
      - redis
    stdin_open: true
    tty: true
  sidekiq:
    build: .
    command: bundle exec sidekiq
    volumes:
      - .:/app
    depends_on:
      - db
      - redis
  redis:
    image: redis
volumes:
  mysql-data:
    driver: local

Sidekiqの設定

Sidekiqを設定する。Gemfileにgem 'sidekiq'を追加し、bundle installを実行する。

Gemfile
gem 'sidekiq'

Sidekiqのダッシュボード機能を利用できるように、routes.rbに以下のコードを追加する。
http://localhost:3000/sidekiqにアクセスすることで実行中のジョブや実行待ちのジョブを確認することができる。

routes.rb
Rails.application.routes.draw do
  require 'sidekiq/web'
  mount Sidekiq::Web => '/sidekiq'
end

Sidekiqの設定ファイルsidekiq.rbを作成する。このファイルでは、SidekiqがRedisサーバーに接続するための設定を行う。

sidekiq.rb
redis_config = { url: 'redis://redis:6379/0' }

Sidekiq.configure_server do |config|
  config.redis = redis_config
end

Sidekiq.configure_client do |config|
  config.redis = redis_config
end

メール送信機能の作成

メールを送信するためのUserMailerを作成する。

user_mailer.rb
class UserMailer < ApplicationMailer
  def reminder_email(user)
    @user = notification.user
    mail(to: @user.email, subject: 'Your reminder')
  end
end

メール送信ジョブの作成

指定した時間にメールを送信するジョブを作成する。app/workersディレクトリに作成する。
ジョブは特定のタスクを実行するためのクラスで、Sidekiq::Workerモジュールをincludeし、performメソッドを定義する。performメソッドは、ジョブが実行されるときに呼び出される。

reminder_mailer_worker.rb
class ReminderMailerWorker
  include Sidekiq::Worker

  def perform(notification_id)
    notification = Notification.find(notification_id)
    UserMailer.reminder_email(notification).deliver_now
  end
end

リマインダーのスケジューリング

リマインダーをスケジュールする。今回は、Notificationモデルにafter_createafter_updateのコールバックを追加し、リマインダーメールの送信をスケジュールする。
ジョブをキューに追加するには、perform_asyncメソッドを使用する。このメソッドは、ジョブをRedisに保存し、その後バックグラウンドで実行される。
下記ではperform_atメソッドを使用して、第一引数にperformメソッドを実行する時間を指定している。

notification.rb
class Notification < ApplicationRecord
  belongs_to :user
  after_save :schedule_reminder_mailer, if: -> { self.datetime.present? }

  private
  def schedule_reminder_mailer
    ReminderMailerWorker.perform_at(self.datetime, self.id)
  end
end

まとめ

今回はSidekiqを使って指定した時間にジョブを実行する方法について紹介した。
sidekiq-cronというgemもあり、こちらは定期的に実行する必要があるジョブを管理することができるよう。

参考文献・URL

sidekiqの使い方
公式GitHub

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2