rails-background-jobs について
Rails のバックグラウンドジョブを設計・設定・レビューするためのガイドです。テストを先に検証し、副作用の前に冪等性を確認する方針を示します。
主な機能
- 01テスト先行の必須手順
- 02冪等性と安全なリトライ
- 03Active Job の引数と責務の指針
- 04Rails 7 と Rails 8 のバックエンド資料
- 05定期ジョブと検証チェックリスト
活用シーン
- 01ジョブのリトライとエラー処理を設計する
- 02メール送信など副作用のあるジョブを実装する
- 03Rails のバージョンに応じたキューバックエンドを選ぶ
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ midudev/ autoskills --skill rails-background-jobsインストール後、Claude Code で/rails-background-jobsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BACKENDS.mdassets/job_patterns.mdretry_examples.md詳細
Rails バックグラウンドジョブ
Rails アプリケーションでバックグラウンドジョブを追加、設定、またはレビューするタスクで、このスキルを使用します。
基本原則: 冪等性と安全な再試行を前提にジョブを設計します。Active Job の統一 API を優先し、Rails のバージョンと規模に応じてバックエンドを選択します。
HARD-GATE
EVERY job MUST have its test written and validated BEFORE implementation.
1. Write the job spec (idempotency, retry, error handling)
2. Run the spec — verify it fails because the job does not exist yet
3. ONLY THEN write the job class
EVERY job that performs a side effect (charge, email, API call) MUST have
an idempotency check BEFORE the side effect.
EVERY perform method should do only three things:
1. Load the record from the passed ID
2. Guard for idempotency / permanent no-op conditions
3. Delegate the side effect or orchestration to a service object
If perform needs more than that, extract a service.
After implementation: run full suite, confirm job appears in queue dashboard,
verify idempotency by enqueueing twice and checking the second run is a no-op.
クイックリファレンス
| 項目 | ルール |
|---|---|
| 引数 | オブジェクトではなく ID を渡します。perform 内で読み込みます。 |
| 冪等性 | 処理を行う前に「すでに完了しているか?」を確認します |
| 再試行 | 一時的なエラーには retry_on、永続的なエラーには discard_on を使用します |
| ジョブの規模 | 読み込み、ガード、委譲を行います。perform 内で複数ステップのオーケストレーションは行いません。 |
| バックエンド(Rails 8) | Solid Queue(データベースベース、Redis 不要) |
| バックエンド(Rails 7) | 高スループットには Sidekiq + Redis |
| 定期実行 | config/recurring.yml(Solid Queue)または cron/sidekiq-cron |
Rails 8 と Rails 7 の比較
| 項目 | Rails 7 以前 | Rails 8 |
|---|---|---|
| デフォルト | デフォルトなし。queue_adapter を設定します(多くの場合 Sidekiq) | Solid Queue(データベースベース) |
| 開発/テスト | :async または :inline | 同じ |
| 定期実行 | 外部(cron、sidekiq-cron) | config/recurring.yml |
| ダッシュボード | サードパーティ(Sidekiq Web) | Mission Control Jobs |
Solid Queue と Sidekiq のインストール手順、設定、ダッシュボードのセットアップについては、BACKENDS.md を参照してください。
例
オブジェクトではなく ID を渡します:
# Bad — object may be stale or deleted by perform time
SomeJob.perform_later(@order)
# Good — reload fresh inside perform
SomeJob.perform_later(@order.id)
冪等性と再試行を備えた薄いジョブ:
class SendInvoiceReminderJob < ApplicationJob
queue_as :default
retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 5
discard_on ActiveRecord::RecordNotFound
def perform(invoice_id)
invoice = Invoice.find(invoice_id)
return if invoice.reminder_sent_at?
InvoiceReminders::Send.call(invoice:)
end
end
副作用と状態更新はサービスが担います:
module InvoiceReminders
class Send
def self.call(invoice:)
InvoiceMailer.overdue(invoice).deliver_now
invoice.update!(reminder_sent_at: Time.current)
end
end
end
定期実行ジョブ(Solid Queue):
# config/recurring.yml
production:
nightly_cleanup:
class: "NightlyCleanupJob"
schedule: "0 2 * * *"
hourly_sync:
class: "HourlySyncJob"
schedule: "every 1 hour"
queue: low
注意点
| 問題 | 正しい方法 |
|---|---|
| ActiveRecord オブジェクトを引数として渡す | ID を渡します。オブジェクトは perform の実行時までに削除されたり、古い状態になったりする可能性があります |
| 副作用の前に冪等性を確認しない | ジョブは少なくとも 1 回実行されるため、二重請求や二重メール送信が発生します |
attempts の上限なしで retry_on を使用する | エラーが解消されない場合に無限に再試行されます |
永続的なエラーに対する discard_on がない | RecordNotFound でジョブが永久に再試行されます |
perform 内に複雑なビジネスロジックを記述する | perform は薄く保ち、サービスオブジェクトに委譲します |
本番環境で :inline または :async を使用する | 永続化、再試行、監視がありません |
| 定期実行ジョブをコード内だけで定義する | 可視性と復旧性を確保するため、recurring.yml または同等の仕組みを使用します |
検証
ジョブを完了とする前に、次の点を確認します。
- ジョブを 2 回エンキューまたは実行し、2 回目の実行で何も行われないことを確認します。
retry_onに明示的なattempts:の上限があり、discard_onが少なくとも 1 つの永続的なエラーを対象としていることを確認します。- 定期実行ジョブが
config/recurring.yml(Rails 8)または選択したスケジューラーの設定に記述されていることを確認します。 performが読み込み、ガード、委譲のみを行うことを確認します。- タスクで運用成果物が求められている場合は、バックエンド、再試行、冪等性に関する決定を
process_log.mdに記録します。
連携
| スキル | 連携するタイミング |
|---|---|
| rails-migration-safety | Solid Queue はデータベーステーブルを使用するため、マイグレーションを安全に追加します |
| rails-security-review | ジョブはシリアライズされた入力を受け取るため、あらゆるエントリーポイントと同様に検証します |
| rspec-best-practices | TDD のゲートとして、実装前にジョブのスペックを作成し、perform_enqueued_jobs を使用します |
| ruby-service-objects | perform を薄く保ち、ビジネスロジックにはサービスオブジェクトを呼び出します |
アセット
コメント
Markdown 対応