Rails8のsolid_queue Redisを使わない非同期処理を試してみる

2024/12/25に公開

はじめに

Rails8からRedisを使わなくても非同期処理ができるようになったので、試してみます。インストールから動作させるところまでと、単一DBで動かす&別DBで動かすの2パターンやりました。

https://github.com/rails/solid_queue

Dockerの設定は以下の通りです。database.ymlでhostを指定するためにここで設定したコンテナ名を使っているので、そこだけ注意してください。

Dockerfile
Dockerfile
FROM ruby:3.3.6

RUN apt-get update -qq \
&& apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /usr/src/app

COPY Gemfile /usr/src/app/Gemfile
COPY Gemfile.lock /usr/src/app/Gemfile.lock
ENV BUNDLER_VERSION 2.6.2
RUN gem update --system \
&& gem install bundler -v $BUNDLER_VERSION \
&& bundle install -j 4

RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
docker-compose.yml
docker-compose.yml
services:
  app:
    build: .
    command:
      [
        '/bin/sh',
        '-c',
        "rm -f tmp/pids/server.pid && bin/dev -b 0.0.0.0 -p 3000",
      ]
    ports:
      - "3000:3000"
    volumes:
      - .:/usr/src/app:delegated
    depends_on:
      - db
      - queue_db
    stdin_open: true
    tty: true
    environment:
      - LANG=C.UTF-8
      - BUNDLE_PATH=vendor/bundle
      - RAILS_ENV=development
    env_file: ./.env
    working_dir: /usr/src/app
  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
    volumes:
      - db:/var/lib/postgresql/data:delegated
  queue_db:
    image: postgres:15
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
    volumes:
      - queue_db:/var/lib/postgresql/data:delegated

volumes:
  db:
    driver: local
  queue_db:
    driver: local

インストール

READMEにしたがってインストールしていきます。(Rails8でnewすると solid_xxx や設定ファイルはデフォルトで入ってるのでスキップ)

Gemfile
gem "solid_cache"
gem "solid_queue"
gem "solid_cable"
bin/rails solid_queue:install

開発環境用のセットアップ

デフォルトでは本番環境で動作させるための設定しか行われていないので、開発環境で動かすためには設定を追加する必要があります。

ref: https://github.com/rails/solid_queue?tab=readme-ov-file#usage-in-development-and-other-non-production-environments

queueを管理するデータベースを設定(単一DBで動かす場合はdevelopment > queueは不要)

database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: db
  port: 5432
  username: postgres
  password: password

development:
  primary:
    <<: *default
    database: app_development
  queue: # 単一DBの場合不要
    <<: *default
    database: app_development_queue
    host: queue_db
    migrations_paths: db/queue_migrate

active_jobのアダプタを設定(単一DBで動かす場合はsolid_queueのconnects_toの設定は不要)

development.rb
  config.active_job.queue_adapter = :solid_queue
  config.solid_queue.connects_to = {database: {writing: :queue}} # 単一DBの場合不要

puma起動時にsolid_queueを起動するよう設定(プロセス作ったりSupervisorを動かしたりしてくれる)

puma.rb
plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] || Rails.env.development?

後は適当に rails g job xxx してperform_laterすると動きます。

単一DB用の一手間

上記の設定に加え、solid_queue用のテーブルを作成する必要があります。(別DBの場合はqueue_schemaからテーブルを作ってくれるっぽい?)

(やり方が正しいかはわかりませんが)適当なmigrationファイルを作成し、 db/queue_schema.rb のcreate_tableを全てコピペし rails db:migrate すればOKです。

ただし、ドキュメントには別DBの利用を推奨すると記載があります。

Discussion