YASD-TECH
YASD TECH
# Rails

Sidekiq非同期ジョブ

投稿日:2026/7/21

更新日:2026/7/22

ttitleImage

概要

重い処理(メール送信・CSV処理・外部API呼び出しなど)をバックグラウンドで実行する仕組み。
キューイングには Redis を使い、Sidekiq ワーカーが順次処理する。

Rails で Sidekiq を使う書き方は大きく2つある。

書き方 ジョブ定義 呼び出し
ActiveJob 経由 class WelcomeEmailJob < ApplicationJob perform_later / perform_now
Sidekiq ネイティブ include Sidekiq::Job perform_async / perform_in / perform_at

ApplicationJob に対して perform_async を使う、というような混ぜ方は避ける。
Rails 標準の ApplicationJob を使うなら perform_later、Sidekiq の API を直接使うなら include Sidekiq::Job に揃える。


基本的な使い方(ActiveJob 経由)

ActiveJob 経由で Sidekiq を使う場合は、ActiveJob の adapter を Sidekiq にしておく。

# config/application.rb など
config.active_job.queue_adapter = :sidekiq

ジョブクラスの定義

class WelcomeEmailJob < ApplicationJob
  def perform(user_id)
    user = User.find(user_id)
    UserMailer.welcome(user).deliver_now
  end
end
  • perform メソッドに実際の処理を書く
  • 引数は ID などの単純な値を渡すのが基本
    • ActiveJob は ActiveRecord オブジェクトも渡せるが、実行時に状態が変わっている可能性があるため ID を渡して find する方が扱いやすい
    • Sidekiq ネイティブ API では、String / Integer / Boolean / Array / Hash など JSON で表現できる値を渡す

ジョブの呼び出し

# 非同期実行(キューに積むだけ。即返る)
WelcomeEmailJob.perform_later(user.id)

# 指定時間後に実行
WelcomeEmailJob.set(wait: 10.minutes).perform_later(user.id)

# 指定日時に実行
WelcomeEmailJob.set(wait_until: Time.zone.tomorrow).perform_later(user.id)

# キューに積まず、その場で同期実行
WelcomeEmailJob.perform_now(user.id)

perform_now 以外は Sidekiq にジョブを登録する処理。
ただし、保存される場所と通常キューへ入るタイミングが違う。

  • perform_later は即実行対象として、すぐ通常のキューに積まれる
  • set(wait: ...) は指定時間後に実行される予約ジョブとして保存され、時刻が来ると通常キューへ移される
  • set(wait_until: ...) は指定日時に実行される予約ジョブとして保存され、時刻が来ると通常キューへ移される
  • perform_now はキューに積まず、現在のプロセスで perform をそのまま実行する

Sidekiq ネイティブ API を使う場合

perform_async などの Sidekiq ネイティブ API を使う場合は、ApplicationJob ではなく Sidekiq::Job を include する。

class WelcomeEmailJob
  include Sidekiq::Job

  def perform(user_id)
    user = User.find(user_id)
    UserMailer.welcome(user).deliver_now
  end
end
# 非同期実行(すぐ通常キューに積む)
WelcomeEmailJob.perform_async(user.id)

# 指定時間後に実行
WelcomeEmailJob.perform_in(10.minutes, user.id)

# 指定日時に実行
WelcomeEmailJob.perform_at(Time.zone.tomorrow, user.id)

# 複数ジョブをまとめて投入
WelcomeEmailJob.perform_bulk([[1], [2], [3]])

# キューに積まず、その場で実行
WelcomeEmailJob.perform_inline(user.id)
WelcomeEmailJob.perform_sync(user.id) # perform_inline の alias

perform_async / perform_in / perform_at は、いずれも Sidekiq にジョブを登録する処理。
ただし、保存される場所と通常キューへ入るタイミングが違う。

  • perform_async は即実行対象として、すぐ通常のキューに積まれる
  • perform_in は指定時間後に実行される予約ジョブとして保存され、時刻が来ると通常キューへ移される
  • perform_at は指定日時に実行される予約ジョブとして保存され、時刻が来ると通常キューへ移される
  • perform_bulk は複数ジョブをまとめて Redis に投入する
  • perform_inline / perform_sync は Redis のキューに積まず、現在のプロセスで即実行する

キューを呼び出しごとに変えたい場合は set を使う。

WelcomeEmailJob.set(queue: :critical).perform_async(user.id)

perform 系メソッドの使い分け

メソッド 対象 挙動
perform 共通 自分で定義する実処理。直接呼ぶより、ジョブ実行時に呼ばれる想定
perform_later ActiveJob ジョブをキューへ登録する
perform_now ActiveJob キューに積まず、その場で perform を実行する
set(wait: ...).perform_later ActiveJob 指定時間後に実行する予約ジョブを登録する
set(wait_until: ...).perform_later ActiveJob 指定日時に実行する予約ジョブを登録する
ActiveJob.perform_all_later ActiveJob 複数の ActiveJob をまとめて登録する
perform_async Sidekiq ネイティブ ジョブを通常キューへ登録する
perform_in Sidekiq ネイティブ 指定時間後に実行する予約ジョブを登録する
perform_at Sidekiq ネイティブ 指定日時に実行する予約ジョブを登録する
perform_bulk Sidekiq ネイティブ 複数ジョブをまとめて登録する
perform_inline Sidekiq ネイティブ キューに積まず、その場で実行する
perform_sync Sidekiq ネイティブ perform_inline の alias

呼び出しメソッドと perform の関係

WelcomeEmailJob.perform_later(user.id)
       ↓ ActiveJob が Sidekiq adapter に渡す
       ↓ 引数を Redis(キュー)に積む
       ↓ 呼び出し元は即座に次の処理へ進む

(後で Sidekiq ワーカーがキューを取り出し)

def perform(user_id)   ← perform_later に渡した引数が来る
  ...
end

Sidekiq ネイティブ API の場合は perform_later の代わりに perform_async を使う。

WelcomeEmailJob.perform_async(user.id)
       ↓ 引数を Redis(キュー)に積む
       ↓ 呼び出し元は即座に次の処理へ進む

(後で Sidekiq ワーカーがキューを取り出し)

def perform(user_id)   ← perform_async に渡した引数が来る
  ...
end

ルール:

  • perform_later は ActiveJob が提供するクラスメソッド
  • perform_async は Sidekiq が提供するクラスメソッド
  • perform は自分で定義するインスタンスメソッド。ここに処理を書く
  • 命名は固定。execute など別名にはできない

エラーハンドリング

class DataImportJob < ApplicationJob
  retry_on StandardError, wait: 10.seconds, attempts: 3

  def perform(file_path, user_id)
    user = User.find(user_id)
    process(file_path)
    notify_success(user)
  rescue StandardError => e
    notify_failure(e, user) if user
    raise  # raise しないとリトライされない
  end
end
  • rescue して例外を握りつぶすと、ジョブが成功した扱いになりリトライされない
  • リトライさせたい場合は raise して例外を再送出する
  • user が nil になりうる場合(find 失敗時)は通知をスキップする
  • Sidekiq ネイティブ API でリトライ回数を指定する場合は sidekiq_options retry: 3 を使う

GraphQL Mutation から呼び出すパターン

重い処理を受け付けるエンドポイントとしてよく使われる。

class Mutations::ImportData < BaseMutation
  field :success, Boolean, null: false

  argument :file_path, String, required: true

  # Mutation 実行前の権限チェック(ready? は必ず実行される)
  def ready?(**_params)
    raise ForbiddenError unless current_user.admin?
    true
  end

  def resolve(file_path:)
    # ジョブをキューに積んで即 success: true を返す
    DataImportJob.perform_later(file_path, context[:current_user].id)
    { success: true }
  end
end

ポイント:

  • resolve の中では重い処理を行わず、ジョブに委譲する
  • フロントはレスポンスを受け取った時点でジョブの完了を待っていない
  • 処理結果はメール・Slack 通知など別の手段でユーザーに伝える
  • DataImportJobinclude Sidekiq::Job のクラスなら、ここは perform_async を使う

使いどころ

処理 同期 or 非同期
メール送信 非同期(ジョブ)
CSV インポート 非同期(ジョブ)
外部 API 呼び出し 非同期(ジョブ)
検索インデックスの更新 非同期(ジョブ)
バリデーション結果を即返す 同期
単純な DB 読み書き 同期

Index

  • 概要
  • 基本的な使い方(ActiveJob 経由)
  • ジョブクラスの定義
  • ジョブの呼び出し
  • Sidekiq ネイティブ API を使う場合
  • perform 系メソッドの使い分け
  • 呼び出しメソッドと perform の関係
  • エラーハンドリング
  • GraphQL Mutation から呼び出すパターン
  • 使いどころ