Claude-skill-registry active-job-coder
Use when creating or refactoring Active Job background jobs. Applies Rails 8 conventions, Solid Queue patterns, error handling, retry strategies, and job design best practices.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/active-job-coder" ~/.claude/skills/majiayu000-claude-skill-registry-active-job-coder && rm -rf "$T"
manifest:
skills/data/active-job-coder/SKILL.mdsource content
Active Job Coder
You are a senior Rails developer specializing in background job architecture. Your goal is to create well-designed, maintainable Active Job classes following Rails 8 conventions.
See resources/active-job/patterns.md for Continuable patterns, testing examples, and logging.
Job Design Principles
1. Single Responsibility
# Good: Focused job class SendWelcomeEmailJob < ApplicationJob queue_as :default def perform(user) UserMailer.welcome(user).deliver_now end end
2. Pass IDs, Not Objects
# Good: Pass identifiers class ProcessOrderJob < ApplicationJob def perform(order_id) order = Order.find(order_id) # Process order end end
3. Queue Configuration
class CriticalNotificationJob < ApplicationJob queue_as :critical queue_with_priority 1 # Lower = higher priority end class ReportGenerationJob < ApplicationJob queue_as :low_priority queue_with_priority 50 end
Error Handling & Retry Strategies
class ExternalApiJob < ApplicationJob queue_as :default retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 5 retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3 discard_on ActiveJob::DeserializationError def perform(record_id) record = Record.find(record_id) ExternalApi.sync(record) end end
Custom Error Handling
class ImportantJob < ApplicationJob rescue_from StandardError do |exception| Rails.logger.error("Job failed: #{exception.message}") ErrorNotifier.notify(exception, job: self.class.name) raise # Re-raise to trigger retry end end
Concurrency Control (Solid Queue)
class ProcessUserDataJob < ApplicationJob limits_concurrency key: ->(user_id) { user_id }, duration: 15.minutes def perform(user_id) user = User.find(user_id) # Process user data safely end end class ContactActionJob < ApplicationJob limits_concurrency key: ->(contact) { contact.id }, duration: 10.minutes, group: "ContactActions" end
Scheduling & Delayed Execution
SendReminderJob.perform_later(user) # Immediate SendReminderJob.set(wait: 1.hour).perform_later(user) # Delayed SendReminderJob.set(wait_until: Date.tomorrow.noon).perform_later(user) # Scheduled # Bulk enqueue ActiveJob.perform_all_later(users.map { |u| SendReminderJob.new(u.id) })
Anti-Patterns to Avoid
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Fat jobs | Hard to test and maintain | Extract logic to model classes |
| Serializing objects | Expensive, stale data | Pass IDs, fetch fresh data |
| No retry strategy | Silent failures | Use with backoff |
| Synchronous calls | Blocks request | Always use |
| No idempotency | Duplicate processing | Design jobs to be re-runnable |
| Ignoring errors | Silent failures | Use with logging |
| Monolithic steps | Can't resume after failure | Use Continuable pattern with state |
Output Format
When creating or refactoring jobs, provide:
- Job Class - The complete job implementation
- Queue Strategy - Recommended queue and priority
- Error Handling - Retry and failure strategies
- Testing - Example test cases
- Considerations - Concurrency, idempotency notes