📋

Solid Queue(Rails)

Redisなし DBだけで — Rails 8デフォルトバックグラウンドジョブシステム

GitHub: rails/solid_queue

Solid Queueは37signalsが作ったDB基盤のActiveJobバックエンドで、Rails 8からデフォルト含まれます。「本当にRedisが必要か?」という問いから始まったプロジェクトです。

詳細なアーキテクチャ分析については韓国語版を参照してください。statusカラムの代わりに別テーブルで状態を管理するコアアイデア、10テーブルのDBスキーマ、ジョブライフサイクル(enqueue → dispatch → claim & execute)、3つのプロセスタイプ(Worker/Dispatcher/Scheduler)、非ブロッキングポーリングのためのFOR UPDATE SKIP LOCKED、enqueue_after_transaction_commit?によるトランザクション安全性が含まれます。

構造ダイアグラム

ジョブ状態別テーブル分離 (ERD)

📋 solid_queue_jobs GitHub ↗
queue_name, class_name, arguments, priority, scheduled_at, finished_at
ON DELETE CASCADE
✅
ready_executions
実行待ち
⏰
scheduled_executions
予約待ち
🔄
claimed_executions
処理中
❌
failed_executions
失敗
🔒
blocked_executions
同時性待ち
🔑
semaphores
同時性制御
ポイント: <strong>statusカラム</strong>の代わりに<strong>状態別テーブル分離</strong>
各テーブルに最適化されたインデックス = 高速ポーリング

ジョブライフサイクル

MyJob.perform_later(args) Job.rb ↗
↓
solid_queue_jobs INSERT + after_create :prepare_for_execution
↓ 即時実行?
↓ 予約?
↓ 同時性制限?
ready_executions
scheduled_executions
blocked_executions
Dispatcher がscheduled → readyに移動 dispatcher.rb ↗
↓
Worker: claim (FOR UPDATE SKIP LOCKED)
ready → claimed (トランザクション)
worker.rb ↗
↓
ActiveJob::Base.execute(arguments)
↓
成功
finished_at更新
↓
失敗
failed_executions

3つのプロセスタイプ

⚙️
Worker
ready_executionsポーリング
↓
claim (SKIP LOCKED)
↓
スレッドプールで実行
worker.rb ↗
📡
Dispatcher
scheduled_executionsポーリング
↓
due済みジョブ → readyに移動
↓
同時性メンテナンス
dispatcher.rb ↗
🔁
Scheduler
cronスケジュール確認
↓
繰り返しジョブenqueue
↓
重複実行防止
scheduler.rb ↗

キーポイント

1

GitHubでrails/solid_queueリポジトリを開く

2

db/migrate/ → 10テーブルスキーマを確認(状態別テーブル分離パターン)

3

lib/solid_queue/worker.rb → ポーリングループとclaimロジックを分析

4

lib/solid_queue/dispatcher.rb → 予約ジョブディスパッチロジックを分析

5

app/models/solid_queue/job.rb → enqueueフローを確認

6

app/models/solid_queue/ready_execution.rb → FOR UPDATE SKIP LOCKEDを確認

7

app/models/solid_queue/claimed_execution.rb → 実行/成功/失敗処理

8

lib/solid_queue/supervisor.rb → Fork vs Asyncプロセス管理

メリット

  • ✓ Redis不要 — DBだけで完全なジョブシステム
  • ✓ Rails 8デフォルト — 別途インストール不要ですぐ使用可能
  • ✓ ActiveJob互換 — 既存ジョブコード変更なしで切替可能
  • ✓ FOR UPDATE SKIP LOCKED — ワーカー間の非ブロッキング競合
  • ✓ 同時性制御内蔵 — セマフォ基盤concurrency limit
  • ✓ Pumaプラグイン — 開発時に別プロセス不要

デメリット

  • ✗ Redis基盤Sidekiqよりスループットが低い場合がある
  • ✗ DB負荷増加 — ジョブが多いとDBに書き込み負担
  • ✗ SQLiteでSKIP LOCKED未サポート(graceful fallback)
  • ✗ 大規模サービスでは依然としてSidekiq/Redisが有利
  • ✗ Web UIがSidekiqより成熟度が低い(Mission Control別途)

ユースケース

メール送信: UserMailer.welcome.deliver_later データ処理: CsvImportJob.perform_later(file) 定期作業: Schedulerで毎日深夜にレポート生成 同時性制御: 同じユーザーの決済ジョブを順次実行 Sidekiq → Solid Queueマイグレーション インストール型アプリでRedisなしでバックグラウンドジョブ処理