0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails初学者】備忘録:Sidekiq-Cronの導入をしてみる

Posted at

ポートフォリオ作成において、翌日の予定があるユーザーにリマインダーメールを自動送信するため、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

導入の流れまとめ!!

  1. Gem を追加して bundle install

    • sidekiqsidekiq-cronを導入
    • Ruby バージョンを3.3.9に変更
  2. 設定ファイルを準備

    • routes.rbにSidekiqダッシュボードのルートを追加
    • application.rbconfig.active_job.queue_adapter = :sidekiqを設定
    • config/initializers/sidekiq.rbにRedis接続とcron読み込みを記述
    • config/sidekiq.ymlでキューを定義
    • config/schedule.ymlに定期ジョブを記述
  3. モデルを修正
    -Notificationモデルにvisitとの関連を追加

    • DBにvisit_idカラムとis_sentフラグを追加
  4. ジョブを作成

    • VisitReminderJobを実装し、翌日のVisitに紐づく通知をメール送信
  5. テスト実行

    • 最初は cron:"*/1 * * * *"で1分ごとに実行して動作確認
    • RailsコンソールからVisitReminderJob.perform_laterで手動テスト
  6. 本番運用

    • cron: "0 9 * * *" に変更し、毎日 9 時に自動実行
    • bundle exec sidekiq -e development -C config/sidekiq.ymlでSidekiqを起動
    • redis-serverを起動してRedisと連携
  7. ダッシュボードで確認・管理

    • /sidekiqダッシュボードでジョブの状態を確認
    • 待機状態・実行中・予定・Cronのジョブ履歴を監視

学んだこと

  • バックグラウンド処理をSidekiqで管理する方法を理解した
  • Sidekiq-Cronを使うことで、定期的な処理を簡単に設定できると学んだ
  • Redisやジョブキューの仕組みを実際に触れることで理解が深まった

初学者のため、間違えていましたらすいません。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?