個人のRailsアプリケーションで使用しているジョブキューイングライブラリをGoodJobからSolidQueueに移行したので必要だった差分等をメモ📝
SolidQueueとは?
SolidQueueは、Rails 8のリリースに伴い、Rails org配下の公式ライブラリとして提供されるようになりました。Rails 8では、デプロイの簡素化と依存関係の削減を目指しており、SolidQueueはその一環として導入されました。
SolidQueueはRedisや他のジョブランナーを不要にし、SQLiteやPostgreSQL、MySQLといったデータベースを利用して高性能なジョブキューイングを実現します。これにより、依存関係が減り、デプロイが容易になるため、今後主流になっていくのかなと思います。
詳細は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が複数データベースに対応していないため、以下を算用して手動でマイグレーションファイルを作成しています。
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.ymlとconfig/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のデフォルト設定では、完了したジョブが自動的にクリーンアップされないため、この設定を追加することで、定期的に完了したジョブを削除し、データベースのパフォーマンスを維持しやすくなります。
おわりに
SolidQueueはMySQLでもRedisに依存しない環境を立てられて良いですね、スケジュール実行等もあり思ったよりも高機能だったのでSolidQueueで十分なプロジェクトも結構ありそうにも思ったので、今後も積極的に利用していきたい📝