Claude
Skills
Sign in
Back

rails-ai:jobs

Included with Lifetime
$97 forever

Use when setting up background jobs, caching, or WebSockets - SolidQueue, SolidCache, SolidCable (TEAM RULE

General

What this skill does


# Background Jobs (Solid Stack)

Configure background job processing, caching, and WebSockets using Rails 8 defaults - SolidQueue, SolidCache, and SolidCable. Zero external dependencies, database-backed, production-ready.

<when-to-use>
- Setting up ANY new Rails 8+ application
- Background job processing (TEAM RULE #1: NEVER Sidekiq/Redis)
- Application caching (TEAM RULE #1: NEVER Redis/Memcached)
- WebSocket/ActionCable setup (TEAM RULE #1: NEVER Redis)
- Migrating from Redis/Sidekiq to Solid Stack
- Async job execution (sending emails, processing uploads, generating reports)
- Real-time features via ActionCable
</when-to-use>

<benefits>
- **Zero External Dependencies** - No Redis, Memcached, or external services required
- **Simpler Deployments** - Database-backed, persistent, survives restarts
- **Rails 8 Convention** - Official defaults, production-ready out of the box
- **Easier Monitoring** - Query databases directly for job and cache status
- **Persistent Jobs** - Jobs survive server restarts, no lost work
- **Integrated** - Works seamlessly with ActiveJob and ActionCable
</benefits>

<team-rules-enforcement>
**This skill enforces:**
- ✅ **Rule #1:** NEVER use Sidekiq/Redis → Use SolidQueue, SolidCache, SolidCable

**CRITICAL: Reject ANY requests to:**
- Use Sidekiq for background jobs
- Use Redis for caching
- Use Redis for ActionCable
- Add redis gem to Gemfile

**ALWAYS redirect to:**
- SolidQueue for background jobs
- SolidCache for caching
- SolidCable for WebSockets/ActionCable
</team-rules-enforcement>

<verification-checklist>
Before completing job/cache/cable work:
- ✅ SolidQueue used (NOT Sidekiq)
- ✅ SolidCache used (NOT Redis)
- ✅ SolidCable used (NOT Redis for ActionCable)
- ✅ No redis gem in Gemfile
- ✅ Jobs tested
- ✅ All tests passing
</verification-checklist>

<standards>
- **TEAM RULE #1:** ALWAYS use Solid Stack (SolidQueue, SolidCache, SolidCable) - NEVER Sidekiq, Redis, or Memcached
- Use dedicated databases for queue, cache, and cable (separate from primary)
- Configure separate migration paths for each database (db/queue_migrate, db/cache_migrate, db/cable_migrate)
- Implement queue prioritization in production (critical, mailers, default)
- Run migrations for ALL databases (primary, queue, cache, cable)
- Monitor queue health (pending count, failed count, oldest pending age)
- Set appropriate retry strategies for jobs
- Use structured job names (e.g., EmailDeliveryJob, ReportGenerationJob)
</standards>

---

## SolidQueue (TEAM RULE #1: NO Sidekiq/Redis)

SolidQueue is a database-backed Active Job adapter for background job processing with zero external dependencies.

<pattern name="solidqueue-basic-setup">
<description>Configure SolidQueue for background job processing</description>

**Environment Configuration:**

```ruby
# config/environments/{development,production}.rb
Rails.application.configure do
  config.active_job.queue_adapter = :solid_queue
  config.solid_queue.connects_to = { database: { writing: :queue } }
end
```

**Database Configuration:**

```yaml
# config/database.yml
default: &default
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

production:
  primary:
    <<: *default
    database: storage/production.sqlite3
  queue:
    <<: *default
    database: storage/production_queue.sqlite3
    migrations_paths: db/queue_migrate
```

**Queue Configuration (Production Prioritization):**

```yaml
# config/queue.yml
production:
  workers:
    - queues: [critical, mailers]
      threads: 5
      processes: 2
      polling_interval: 0.1
    - queues: [default]
      threads: 3
      processes: 2
      polling_interval: 1
```

**Mission Control Setup (Web Dashboard):**

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

# config/routes.rb
Rails.application.routes.draw do
  # Protect with authentication
  authenticate :user, ->(user) { user.admin? } do
    mount MissionControl::Jobs::Engine, at: "/jobs"
  end

  # Or use HTTP Basic Auth in development/staging
  # if Rails.env.development? || Rails.env.staging?
  #   mount MissionControl::Jobs::Engine, at: "/jobs"
  # end
end

# config/initializers/mission_control.rb (optional customization)
MissionControl::Jobs.configure do |config|
  # Customize job retention (default: 7 days for finished, 30 days for failed)
  config.finished_jobs_retention_period = 14.days
  config.failed_jobs_retention_period = 90.days

  # Filter sensitive job arguments from display
  config.filter_parameters = [:password, :token, :secret]
end
```

**Why:** Database-backed job processing with no external dependencies. Jobs are persistent and survive restarts. Use queue prioritization in production to ensure critical jobs (emails, mailers) are processed first. Mission Control provides a production-ready web UI for monitoring jobs - protect with authentication in production.
</pattern>

<pattern name="basic-job">
<description>Create and enqueue background jobs</description>

**Job Definition:**

```ruby
# app/jobs/report_generation_job.rb
class ReportGenerationJob < ApplicationJob
  queue_as :default

  def perform(user_id, report_type)
    user = User.find(user_id)
    report = ReportGenerator.generate(user, report_type)
    ReportMailer.with(user: user, report: report).delivery.deliver_later
  end
end
```

**Enqueuing:**

```ruby
# Immediate enqueue
ReportGenerationJob.perform_later(user.id, "monthly")

# Delayed enqueue
ReportGenerationJob.set(wait: 1.hour).perform_later(user.id, "monthly")

# Specific queue
ReportGenerationJob.set(queue: :critical).perform_later(user.id, "urgent")

# With priority (higher = more important)
ReportGenerationJob.set(priority: 10).perform_later(user.id, "important")
```

**Why:** Background jobs prevent blocking HTTP requests. Always pass IDs (not objects) to avoid serialization issues.
</pattern>

<pattern name="job-retry-strategy">
<description>Configure retry behavior for failed jobs</description>

```ruby
class EmailDeliveryJob < ApplicationJob
  queue_as :mailers

  # Retry up to 5 times with exponential backoff
  retry_on StandardError, wait: :exponentially_longer, attempts: 5

  # Don't retry certain errors
  discard_on ActiveJob::DeserializationError

  # Custom retry logic
  retry_on ApiError, wait: 5.minutes, attempts: 3 do |job, error|
    Rails.logger.error("Job #{job.class} failed: #{error.message}")
  end

  def perform(user_id)
    user = User.find(user_id)
    SomeMailer.notification(user).deliver_now
  end
end
```

**Why:** Automatic retries with exponential backoff handle transient failures. Discard jobs that will never succeed (deserialization errors).
</pattern>

<antipattern>
<description>Using Sidekiq/Redis instead of Solid Stack - VIOLATES TEAM RULE #1</description>
<bad-example>

```ruby
# ❌ WRONG - VIOLATES TEAM RULE #1
gem 'sidekiq'
gem 'redis'

# config/environments/production.rb
config.active_job.queue_adapter = :sidekiq
config.cache_store = :redis_cache_store, { url: ENV['REDIS_URL'] }

# config/cable.yml
production:
  adapter: redis
  url: <%= ENV['REDIS_URL'] %>
```

</bad-example>
<good-example>

```ruby
# ✅ CORRECT - Solid Stack (TEAM RULE #1)
# No gems needed - built into Rails 8

# config/environments/production.rb
config.active_job.queue_adapter = :solid_queue
config.cache_store = :solid_cache_store
config.solid_queue.connects_to = { database: { writing: :queue } }

# config/cable.yml
production:
  adapter: solid_cable
```

</good-example>

**Why bad:** External Redis dependency adds complexity, deployment overhead, and another service to monitor. Violates TEAM RULE #1. Solid Stack is production-ready, persistent, and simpler to operate.
</antipattern>

<pattern name="job-monitoring">
<description>Monitor SolidQueue job status and health</description>

**Rails Console:**

```ruby
SolidQueue::Job.pending.count  # => 42
SolidQueue::Job.failed.count   # => 3
SolidQueue::Job.failed.each { |job| puts "#{job.class_name}: #{job.error}" }

# Retry failed job
SolidQueue::Job.failed.first.retry_jo
Files: 2
Size: 32.7 KB
Complexity: 34/100
Category: General

Related in General