home / skills / thibautbaissac / rails_ai_agents / solid-queue-setup

solid-queue-setup skill

/skills/solid-queue-setup

This skill helps Rails developers configure Solid Queue for background jobs, from installation to recurring tasks, with adapters, queues, and monitoring.

npx playbooks add skill thibautbaissac/rails_ai_agents --skill solid-queue-setup

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
5.6 KB
---
name: solid-queue-setup
description: Configures Solid Queue for background jobs in Rails 8. Use when setting up background processing, creating background jobs, configuring job queues, or migrating from Sidekiq to Solid Queue.
allowed-tools: Read, Write, Edit, Bash
---

# Solid Queue Setup for Rails 8

## Overview

Solid Queue is Rails 8's default Active Job backend:
- Database-backed (no Redis required)
- Built-in concurrency controls
- Supports priorities and multiple queues
- Mission-critical job processing
- Web UI available via Mission Control

## Quick Start

### Installation

```bash
# Add to Gemfile (included in Rails 8 by default)
bundle add solid_queue

# Install Solid Queue
bin/rails solid_queue:install

# Run migrations
bin/rails db:migrate
```

### Configuration

```yaml
# config/solid_queue.yml
default: &default
  dispatchers:
    - polling_interval: 1
      batch_size: 500
  workers:
    - queues: "*"
      threads: 3
      processes: 1
      polling_interval: 0.1

development:
  <<: *default

production:
  <<: *default
  workers:
    - queues: [critical, default]
      threads: 5
      processes: 2
    - queues: [low]
      threads: 2
      processes: 1
```

### Set as Active Job Adapter

```ruby
# config/application.rb
config.active_job.queue_adapter = :solid_queue

# Or per environment
# config/environments/production.rb
config.active_job.queue_adapter = :solid_queue
```

## Workflow Checklist

```
Solid Queue Setup:
- [ ] Add solid_queue gem
- [ ] Run solid_queue:install
- [ ] Run migrations
- [ ] Configure queues in solid_queue.yml
- [ ] Set queue adapter in config
- [ ] Create first job with spec
- [ ] Test job execution
- [ ] Configure recurring jobs (if needed)
```

## Creating Jobs

### Basic Job

```ruby
# app/jobs/send_welcome_email_job.rb
class SendWelcomeEmailJob < ApplicationJob
  queue_as :default

  def perform(user_id)
    user = User.find(user_id)
    UserMailer.welcome(user).deliver_now
  end
end
```

### Job with Retries

```ruby
# app/jobs/process_payment_job.rb
class ProcessPaymentJob < ApplicationJob
  queue_as :critical

  # Retry on specific errors
  retry_on PaymentGatewayError, wait: :polynomially_longer, attempts: 5

  # Don't retry on these
  discard_on ActiveRecord::RecordNotFound

  # Custom error handling
  rescue_from(StandardError) do |exception|
    ErrorNotifier.notify(exception)
    raise # Re-raise to trigger retry
  end

  def perform(order_id)
    order = Order.find(order_id)
    PaymentService.new.charge(order)
  end
end
```

### Job with Priority

```ruby
class UrgentNotificationJob < ApplicationJob
  queue_as :critical

  # Lower number = higher priority
  # Default is 0
  def priority
    -10
  end

  def perform(notification_id)
    # Process urgent notification
  end
end
```

## Enqueueing Jobs

```ruby
# Enqueue immediately
SendWelcomeEmailJob.perform_later(user.id)

# Enqueue with delay
SendReminderJob.set(wait: 1.hour).perform_later(user.id)

# Enqueue at specific time
SendReportJob.set(wait_until: Date.tomorrow.noon).perform_later

# Enqueue on specific queue
ProcessJob.set(queue: :low).perform_later(data)

# Perform immediately (skips queue - use sparingly)
SendWelcomeEmailJob.perform_now(user.id)
```

## Recurring Jobs

```yaml
# config/recurring.yml
production:
  daily_report:
    class: GenerateDailyReportJob
    schedule: every day at 6am
    queue: low

  cleanup:
    class: CleanupOldRecordsJob
    schedule: every sunday at 2am

  sync:
    class: SyncExternalDataJob
    schedule: every 15 minutes
```

## Testing Jobs

### Job Spec Template

```ruby
# spec/jobs/send_welcome_email_job_spec.rb
require 'rails_helper'

RSpec.describe SendWelcomeEmailJob, type: :job do
  let(:user) { create(:user) }

  describe '#perform' do
    it 'sends welcome email' do
      expect {
        described_class.perform_now(user.id)
      }.to have_enqueued_mail(UserMailer, :welcome)
    end
  end

  describe 'enqueueing' do
    it 'enqueues the job' do
      expect {
        described_class.perform_later(user.id)
      }.to have_enqueued_job(described_class)
        .with(user.id)
        .on_queue('default')
    end
  end

  describe 'retry behavior' do
    it 'retries on PaymentGatewayError' do
      expect(described_class).to have_retry_on(PaymentGatewayError)
    end
  end
end
```

### Test Helpers

```ruby
# spec/rails_helper.rb
RSpec.configure do |config|
  config.include ActiveJob::TestHelper
end

# In specs
it 'processes all jobs' do
  perform_enqueued_jobs do
    UserSignupService.call(user_params)
  end
  expect(user.reload.welcome_email_sent?).to be true
end

it 'enqueues multiple jobs' do
  expect {
    BatchProcessor.process(items)
  }.to have_enqueued_job(ProcessItemJob).exactly(items.count).times
end
```

## Running Solid Queue

```bash
# Development (runs in separate terminal)
bin/rails solid_queue:start

# Production (via Procfile)
# Procfile
web: bin/rails server
worker: bin/rails solid_queue:start
```

## Monitoring

### Mission Control (Web UI)

```ruby
# Gemfile
gem "mission_control-jobs"

# config/routes.rb
mount MissionControl::Jobs::Engine, at: "/jobs"
```

### Console Queries

```ruby
# Check pending jobs
SolidQueue::Job.where(finished_at: nil).count

# Check failed jobs
SolidQueue::FailedExecution.count

# Retry failed job
SolidQueue::FailedExecution.last.retry

# Clear old completed jobs
SolidQueue::Job.where('finished_at < ?', 1.week.ago).delete_all
```

## Migration from Sidekiq

| Sidekiq | Solid Queue |
|---------|-------------|
| `perform_async(args)` | `perform_later(args)` |
| `perform_in(5.minutes, args)` | `set(wait: 5.minutes).perform_later(args)` |
| `sidekiq_options queue: 'critical'` | `queue_as :critical` |
| `sidekiq_retry_in` | `retry_on` with `wait:` |

Overview

This skill configures Solid Queue as the Active Job backend for Rails 8 apps and guides background job setup, testing, and migration from Sidekiq. It provides installation steps, configuration examples, job patterns (retries, priorities, recurring jobs), and monitoring tips. Use it to get a robust, database-backed job system running with minimal external dependencies.

How this skill works

The skill installs and configures the solid_queue gem, creates the required database tables, and sets Solid Queue as Rails' active_job adapter. It generates a solid_queue.yml for dispatcher/worker tuning, shows how to create jobs with retries and priorities, and demonstrates enqueueing, recurring schedules, and how to run workers locally or in production. It also covers test helpers and Mission Control integration for observability.

When to use it

  • Setting up background processing in a new Rails 8 app
  • Creating jobs with retries, priorities, or custom error handling
  • Configuring worker threads/processes and queue routing
  • Migrating existing Sidekiq jobs to Solid Queue
  • Adding recurring jobs and scheduling without Redis

Best practices

  • Keep solid_queue.yml under source control and tune threads/processes per environment
  • Use queue_as and explicit queue names for predictable routing
  • Retry only on recoverable errors and use discard_on for not-found records
  • Write RSpec job specs using ActiveJob::TestHelper and perform_enqueued_jobs for integration checks
  • Monitor with Mission Control and periodically prune old completed jobs

Example use cases

  • SendWelcomeEmailJob.perform_later(user.id) to enqueue user emails without Redis
  • Define ProcessPaymentJob with retry_on to handle transient payment gateway failures
  • Run bin/rails solid_queue:start in a worker process or via Procfile for production
  • Create recurring tasks in config/recurring.yml for daily reports or cleanup jobs
  • Migrate Sidekiq calls: replace perform_async with perform_later and sidekiq options with queue_as

FAQ

Do I need Redis to use Solid Queue?

No. Solid Queue is database-backed and does not require Redis.

How do I set Solid Queue as the Active Job adapter?

Set config.active_job.queue_adapter = :solid_queue in application.rb or the target environment file.

How can I inspect failed jobs?

Use SolidQueue::FailedExecution in the console to list and retry failures, or mount Mission Control for a web UI.