🔧

MaintenanceTasks + SolidQueueで「signal 6」エラーが発生した時の解決法

に公開

問題の概要

Rails アプリケーションで MaintenanceTasks を使用してメンテナンスタスクを実行中、SolidQueue で以下のようなエラーが発生しました。

SolidQueue::Processes::ProcessExitError
Message: Process pid=67893 exited unexpectedly. Received unhandled signal 6.

このエラーは「子プロセスが SIGABRT(シグナル6)で異常終了した」ことを意味し、Ruby例外として表面に現れないため、原因の特定が困難な状況でした。

エラーの詳細

発生状況

  • タスク: MaintenanceTasks::TaskJob
  • キューシステム: SolidQueue
  • 実行モード: プロセス実行モード
  • エラータイプ: SolidQueue::Processes::ProcessExitError
  • シグナル: 6 (SIGABRT)

Raw データ

{
  "class_name": "MaintenanceTasks::TaskJob",
  "arguments": [
    {
      "_aj_globalid": "gid://m4g3/MaintenanceTasks::Run/1"
    }
  ],
  "queue_name": "default",
  "priority": 0,
  "scheduled_at": "2025-09-08T15:24:32.690Z"
}

解決のアプローチ

1. エラーの可視化

SolidQueue のプロセス実行モードでは、子プロセスで発生した例外が Ruby のスタックトレースとして表示されません。そこで、一時的に inline 実行 に切り替えて真の原因を特定することにしました。

# config/environments/development.rb
config.active_job.queue_adapter = :inline

2. 真の原因の発見

inline 実行に切り替えた結果、以下のエラーが明確になりました:

Maintenance::UpdateProductCreatedAtTask#collection must be either an 
Active Record Relation, ActiveRecord::Batches::BatchEnumerator, Array, or CSV.

根本原因

MaintenanceTasks gem は以下の型のみをサポートしていますが、Mongoid の Criteria オブジェクトは含まれていませんでした:

  • Active Record Relation
  • ActiveRecord::Batches::BatchEnumerator
  • Array
  • CSV

問題のあったコード

class Maintenance::UpdateProductCreatedAtTask < MaintenanceTasks::Task
  def collection = Mongoid::Product.where(created_at: nil)  # ← Mongoid::Criteria
  def process(product) = product.update(created_at: product.user.created_at, updated_at: product.user.created_at)
end

Mongoid::Product.where(created_at: nil)Mongoid::Criteria オブジェクトを返すため、MaintenanceTasks でサポートされていませんでした。

修正内容

collection を ID の Array に変更し、process メソッドで個別に find する方式に修正しました:

class Maintenance::UpdateProductCreatedAtTask < MaintenanceTasks::Task
  def collection = Mongoid::Product.where(created_at: nil).pluck(:id)
  def count = Mongoid::Product.where(created_at: nil).count
  
  def process(id)
    product = Mongoid::Product.find(id)
    product.update(created_at: product.user.created_at, updated_at: product.user.created_at)
  end
end

修正のポイント

  1. collection: pluck(:id) で ID の配列を返す
  2. count: 進捗表示のために件数を返すメソッドを追加
  3. process: ID を受け取って毎回 find する方式に変更

学んだこと

SolidQueue のプロセス実行モードでのデバッグ手法

プロセス実行モードでは子プロセスの例外が見えないため、以下の手順でデバッグするのが効果的です:

  1. inline 実行への一時切り替え

    config.active_job.queue_adapter = :inline
    
  2. スレッド実行モードへの切り替え(代替案)

    # config/queue.yml
    development:
      workers:
        - queues: "*"
          threads: 5
          processes: 1  # プロセス数を1に制限
    

MaintenanceTasks と Mongoid の組み合わせ

  • MaintenanceTasks は ActiveRecord 前提で設計されている
  • Mongoid を使用する場合は、collection に Array や CSV を渡す必要がある
  • 300件程度の小規模データなら pluck(:id)find(id) パターンで十分

まとめ

SolidQueue + MaintenanceTasks で「signal 6」エラーが発生した場合:

  1. まず inline 実行で真の原因を特定する
  2. MaintenanceTasks の collection 仕様を確認する
  3. Mongoid 使用時は ID Array パターンを採用する

この手法により、見た目は複雑な「プロセス異常終了」エラーも、実際は単純な API 仕様の問題であることが判明し、迅速に解決することができました。

Discussion