Madogiwa Blog

主に技術系の学習メモに使っていきます。

Ruby on Rails: GoodJobからSolidQueueへの移行したのでメモ📝

個人のRailsアプリケーションで使用しているジョブキューイングライブラリをGoodJobからSolidQueueに移行したので必要だった差分等をメモ📝

SolidQueueとは?

SolidQueueは、Rails 8のリリースに伴い、Rails org配下の公式ライブラリとして提供されるようになりました。Rails 8では、デプロイの簡素化と依存関係の削減を目指しており、SolidQueueはその一環として導入されました。

SolidQueueはRedisや他のジョブランナーを不要にし、SQLitePostgreSQLMySQLといったデータベースを利用して高性能なジョブキューイングを実現します。これにより、依存関係が減り、デプロイが容易になるため、今後主流になっていくのかなと思います。

詳細はRails 8のリリースノートを参照してください。

Solid Queueのインストール

まず、GemfileからGoodJobを削除し、SolidQueueを追加します。またSolidQueueのダッシュボードのためにMission Control — Jobsも追加します。

- gem "good_job"
+ gem "solid_queue", "~> 1.1"
+ gem "mission_control-jobs"

次に、bundle installを実行してGemfile.lockを更新します。

$ bundle install

設定ファイルの更新

config/application.rbでActiveJobのアダプターをGoodJobからSolidQueueに変更します。また、SolidQueueの接続設定を追加します。

- config.active_job.queue_adapter = :good_job
+ config.active_job.queue_adapter = :solid_queue
+ config.solid_queue.connects_to = {database: {writing: :primary, reading: :primary}}

デフォルトでは「config.solid_queue.connects_to = { database: { writing: :queue } }」を指定しますが、本番環境でHerokuを使用しており、Herokuは複数のデータベースを持てないのでprimaryに接続するようにしています。

Unlike Amazon RDS, Heroku doesn't allow creating multiple databases – your DB role simply doesn't have permissions to CREATE DATABASE ..;. https://stackoverflow.com/questions/45316858/is-it-possible-to-have-multiple-databases-per-one-heroku-postgres-plan

We typically see CONNECT privilege errors in cases where applications try to create databases as part of running db:setup, given that the Heroku Postgres credential provided does not have privileges to create or drop databases. https://help.heroku.com/63D7ALXT/why-am-i-seeing-user-does-not-have-connect-privilege-error-with-heroku-postgres-on-review-apps

また、GoodJobの初期化ファイルを削除し、MissionControlの初期化ファイルを追加します。

- config/initializers/good_job.rb
+ config/initializers/mission_control.rb

config/initializers/mission_control.rbの内容は以下の通りです。

Rails.application.configure do
  MissionControl::Jobs.base_controller_class = "Admin::ApplicationController"
end

マイグレーションの実行

SolidQueueのテーブルを作成し、GoodJobのテーブルを削除するマイグレーションを追加します。

SolidQueueのテーブル作成

db/migrate/20241229000000_create_solidqueue_tables.rbを作成し、以下の内容を追加します。

class CreateSolidqueueTables < ActiveRecord::Migration[7.2]
  def change
    # SolidQueueのテーブル作成コード
  end
end

SolidQueueのREADMEでは、bin/rails solid_queue:installコマンドを使用してテーブルを作成する手順が記載されていますが、Herokuが複数データベースに対応していないため、以下を算用して手動でマイグレーションファイルを作成しています。

github.com

GoodJobのテーブル削除

db/migrate/20241229000001_drop_good_job_tables.rbを作成し、以下の内容を追加します。

class DropGoodJobTables < ActiveRecord::Migration[7.2]
  def change
    # GoodJobのテーブル削除コード
  end
end

ルーティングの更新

config/routes/admin.rbでGoodJobのルートをMissionControlのルートに変更します。

- mount GoodJob::Engine => "good_job"
+ mount MissionControl::Jobs::Engine, at: "/jobs"

その他の設定

Pumaの設定

PumaとSolidQueueのプロセスを共存させるために、config/puma.rbに以下の設定を追加します。

plugin :solid_queue

PumaとSolidQueueのプロセスを共存させることで、コスト削減のためにPumaとSolidQueueを同じプロセスで実行する設定です。詳細はSolidQueueのREADMEを参照してください。

キュー設定ファイルの追加

config/queue.ymlconfig/recurring.ymlを作成し、SolidQueueの設定を追加します。

# config/queue.yml
default: &default
  dispatchers:
    - polling_interval: 1
      batch_size: 500
  workers:
    - queues: "*"
      threads: 3
      processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
      polling_interval: 0.1

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default
# config/recurring.yml
default: &default
  bulk_entries_recreate_job:
    class: BulkEntriesRecreateJob
    schedule: "0 * * * *"
  clear_finished_job:
    command: "SolidQueue::Job.clear_finished_in_batches"
    schedule: "30 0 * * *"

production:
  <<: *default

development:
  <<: *default

clear_finished_jobは、完了したジョブを定期的にクリーンアップするための設定です。SolidQueueのデフォルト設定では、完了したジョブが自動的にクリーンアップされないため、この設定を追加することで、定期的に完了したジョブを削除し、データベースのパフォーマンスを維持しやすくなります。

github.com

おわりに

SolidQueueはMySQLでもRedisに依存しない環境を立てられて良いですね、スケジュール実行等もあり思ったよりも高機能だったのでSolidQueueで十分なプロジェクトも結構ありそうにも思ったので、今後も積極的に利用していきたい📝