ポートフォリオ作成において、翌日の予定があるユーザーにリマインダーメールを自動送信するため、Sidekiq・Sidekiq-cronを導入しました。
概要
- 定期実行バッチを管理するためにSidekiq、Sidekiq-cronを導入
- 翌日に予定があるユーザーに毎日自動でリマインダーメールを送信する機能を実装
- 使用 Gem:
- sidekiq
- sidekiq-cron
gemの追加
Gemfile
gem "active_storage_validations"
gem "image_processing", ">= 1.2"
gem "sidekiq"
gem "sidekiq-cron", "~> 2.3"
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[ windows jruby ]
Ruby バージョン変更(互換性エラーが出たため)
-3.4.2
+3.3.9
設定ファイル
routes.rb
require "sidekiq/web"
require "sidekiq/cron/web"
Rails.application.routes.draw do
mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?
end
config/application.rb
# sidekiq設定
config.active_job.queue_adapter = :sidekiq
config/initializers/sidekiq.rb
# frozen_string_literal: true
redis_config = Rails.application.config_for('settings/redis')
Sidekiq.configure_server do |config|
config.redis = { url: "redis://#{redis_config[:host]}:#{redis_config[:port]}/#{redis_config[:db]}" }
end
Sidekiq.configure_client do |config|
config.redis = { url: "redis://#{redis_config[:host]}:#{redis_config[:port]}/#{redis_config[:db]}" }
end
# sidekiq_cronの設定
schedule_file = 'config/schedule.yml'
Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) if File.exist?(schedule_file) && Sidekiq.server?
config/sidekiq.yml
:concurrency: 1
:queues:
- default
- mailer
config/schedule.yml
1分ごとにとりあえず送れるかテストするための設定
visit_reminder_job:
cron: "*/1 * * * *"
class: "VisitReminderJob"
queue: "default"
description: "翌日の予定があるユーザーにリマインダーメールを送信する"
active_job: true
→ テスト後、毎日9時に変更する
visit_reminder_job:
- cron: "*/1 * * * *"
+ cron: "0 9 * * *"
class: "VisitReminderJob"
queue: "default"
description: "翌日の予定があるユーザーにリマインダーメールを送信する"
モデルの変更
app/models/notification.rb
class Notification < ApplicationRecord
- belongs_to :user
+ belongs_to :visit
validates :title, :due_date, presence: true
end
DBスキーマ変更
t.boolean "is_sent", default: false, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "visit_id", null: false
t.index ["user_id"], name: "index_notifications_on_user_id"
t.index ["visit_id"], name: "index_notifications_on_visit_id"
ジョブの実装
app/jobs/visit_reminder_job.rb
class VisitReminderJob < ApplicationJob
queue_as :default
def perform
# 翌日が予定日の visit に紐づく通知を探してメール送信
Visit.where(visit_date: Date.tomorrow).find_each do |visit|
visit.notifications.each do |notification|
NotificationMailer.visit_reminder(notification).deliver_later
end
end
end
end
導入の流れまとめ!!
-
Gem を追加して bundle install
-
sidekiqとsidekiq-cronを導入 - Ruby バージョンを
3.3.9に変更
-
-
設定ファイルを準備
-
routes.rbにSidekiqダッシュボードのルートを追加 -
application.rbでconfig.active_job.queue_adapter = :sidekiqを設定 -
config/initializers/sidekiq.rbにRedis接続とcron読み込みを記述 -
config/sidekiq.ymlでキューを定義 -
config/schedule.ymlに定期ジョブを記述
-
-
モデルを修正
-Notificationモデルにvisitとの関連を追加- DBに
visit_idカラムとis_sentフラグを追加
- DBに
-
ジョブを作成
-
VisitReminderJobを実装し、翌日のVisitに紐づく通知をメール送信
-
-
テスト実行
- 最初は
cron:"*/1 * * * *"で1分ごとに実行して動作確認 - Railsコンソールから
VisitReminderJob.perform_laterで手動テスト
- 最初は
-
本番運用
-
cron: "0 9 * * *"に変更し、毎日 9 時に自動実行 -
bundle exec sidekiq -e development -C config/sidekiq.ymlでSidekiqを起動 -
redis-serverを起動してRedisと連携
-
-
ダッシュボードで確認・管理
-
/sidekiqダッシュボードでジョブの状態を確認 - 待機状態・実行中・予定・Cronのジョブ履歴を監視
-
学んだこと
- バックグラウンド処理をSidekiqで管理する方法を理解した
- Sidekiq-Cronを使うことで、定期的な処理を簡単に設定できると学んだ
- Redisやジョブキューの仕組みを実際に触れることで理解が深まった
初学者のため、間違えていましたらすいません。