7.6 KiB
Job Scheduling with Solid Queue
This document explains how stock-related jobs are scheduled to run automatically using Rails 8's Solid Queue system.
Overview
The application uses Solid Queue for both job processing and recurring job scheduling. This provides a unified, database-backed system that works identically across all environments (development, staging, production).
Scheduled Jobs
- OrderExecutionJob - Executes pending stock orders (both buy and sell) at 1:00 AM ET weekdays only (Monday-Friday)
- StockPricesUpdateJob - Updates stock prices from Alpha Vantage API (automatically triggered after OrderExecutionJob)
- MonthlyPortfolioSnapshotJob - Creates portfolio snapshots on the last day of each month at 11:00 PM ET
Configuration
Recurring Jobs Configuration
The scheduling configuration is defined in config/recurring.yml:
development: &default
daily_order_execution:
class: OrderExecutionJob
queue: default
schedule: "0 6 * * 1-5" # Monday-Friday at 6 AM UTC (1 AM EST)
monthly_portfolio_snapshot:
class: MonthlyPortfolioSnapshotJob
queue: default
schedule: "0 23 L * *" # Last day of month at 11 PM UTC
production:
<<: *default
Worker Configuration
Worker settings are configured in 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
Job Execution Flow
Daily Stock Processing (1:00 AM ET, Weekdays Only)
-
OrderExecutionJob runs first (scheduled via recurring.yml)
- Processes all pending buy/sell orders
- Applies transaction fees
- Automatically triggers StockPricesUpdateJob upon completion
- Only runs Monday through Friday (weekdays)
-
StockPricesUpdateJob runs second (triggered by OrderExecutionJob)
- Updates current stock prices from Alpha Vantage API
- Saves yesterday's prices for historical tracking
- Only runs on weekdays (when OrderExecutionJob runs)
Monthly Portfolio Snapshots (Last Day, 11:00 PM ET)
- MonthlyPortfolioSnapshotJob runs monthly
- Creates portfolio snapshots for all students
- Used for performance tracking and reporting
Deployment Instructions
Development Environment
Start the Solid Queue worker to process jobs:
# Start worker in development
bin/jobs
# Or run in background
bin/jobs &
Test job scheduling:
# Test manual job execution
rails console
OrderExecutionJob.perform_later
SolidQueue::Job.count # Should show queued jobs
Staging Deployment
Heroku
# Deploy code changes
git push heroku main
# Scale up job worker (uses Procfile configuration)
heroku ps:scale job=1 -a your-app-name
# Verify worker is running
heroku ps -a your-app-name
AWS/Traditional Servers
Create a systemd service for the worker:
# /etc/systemd/system/stocks-solid-queue.service
[Unit]
Description=Stocks in the Future - Solid Queue Worker
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/path/to/your/app
ExecStart=/path/to/your/app/bin/jobs
Restart=always
RestartSec=5
Environment=RAILS_ENV=production
Environment=JOB_CONCURRENCY=3
[Install]
WantedBy=multi-user.target
# Enable and start service
sudo systemctl enable stocks-solid-queue
sudo systemctl start stocks-solid-queue
sudo systemctl status stocks-solid-queue
Job Dependencies
Prerequisites
- Database Access: All job data is stored in PostgreSQL
- Active Worker Process: Must have
bin/jobsrunning - API Access: StockPricesUpdateJob requires Alpha Vantage API access
- Environment Variables:
ALPHA_VANTAGE_API_KEYmust be set
Database Tables
Solid Queue uses these database tables:
solid_queue_jobs- Main job queuesolid_queue_ready_executions- Jobs ready to runsolid_queue_recurring_executions- Recurring job schedulessolid_queue_failed_executions- Failed jobs for debugging
Monitoring
Job Status Monitoring
# Check job counts
rails console
SolidQueue::Job.count # Total jobs
SolidQueue::Job.where(finished_at: nil).count # Pending jobs
SolidQueue::FailedExecution.count # Failed jobs
# View recent jobs
SolidQueue::Job.last(10).each do |job|
puts "#{job.class_name} - #{job.finished_at ? 'Complete' : 'Pending'}"
end
Heroku Monitoring
# View job logs
heroku logs --tail -a your-app-name | grep -E "(OrderExecutionJob|StockPricesUpdateJob)"
# Check worker status
heroku ps -a your-app-name
# Check job queue
heroku run rails runner "puts SolidQueue::Job.count" -a your-app-name
Log Files
Monitor execution through:
- Rails logs:
log/production.log(contains job execution details) - Worker logs: Output from
bin/jobsprocess - Heroku logs:
heroku logs --tail -a your-app-name
Manual Execution
For testing or emergency runs:
# Rails console
rails console
OrderExecutionJob.perform_later # Queue job
OrderExecutionJob.perform_now # Run immediately
StockPricesUpdateJob.perform_later # Queue job
MonthlyPortfolioSnapshotJob.perform_later # Queue monthly job
# Command line
rails runner "OrderExecutionJob.perform_later"
Troubleshooting
Common Issues
-
Jobs not running:
- Check worker process is running (
bin/jobs) - Verify database connection
- Check
solid_queue_jobstable exists
- Check worker process is running (
-
Jobs failing:
- Check
SolidQueue::FailedExecution.allfor error details - Verify API keys are set (
ALPHA_VANTAGE_API_KEY) - Check database connectivity
- Check
-
Recurring jobs not scheduling:
- Verify
config/recurring.ymlsyntax - Check worker is running with recurring job support
- Confirm time zone settings
- Verify
-
Performance issues:
- Adjust
JOB_CONCURRENCYenvironment variable - Monitor database table sizes
- Check API rate limits
- Adjust
Debugging Commands
# View failed jobs with errors
rails console
SolidQueue::FailedExecution.all.each do |failed_job|
puts "#{failed_job.job.class_name}: #{failed_job.error}"
end
# Check recurring job schedules
SolidQueue::RecurringTask.all.each do |task|
puts "#{task.class_name}: #{task.schedule}"
end
# Clear all jobs (emergency only)
SolidQueue::Job.delete_all
Time Zone Considerations
- Recurring jobs use server time zone
- Jobs are scheduled in Eastern Time (America/New_York)
- Heroku: Runs in UTC, so 1 AM ET = 6 AM UTC (EST) or 5 AM UTC (EDT)
- AWS: Configure server time zone or adjust schedule accordingly
- Weekday scheduling: OrderExecutionJob and StockPricesUpdateJob only run Monday-Friday
Migration from Previous System
This system replaces the previous setup that used:
- ❌ whenever gem (removed) - No longer needed
- ❌ Heroku Scheduler (removed) - No longer needed
- ❌ Delayed Job (removed) - Replaced by Solid Queue
- ❌ cron jobs (removed) - No longer needed
Benefits of New System
- ✅ Environment independent - Works same on Heroku and AWS
- ✅ Database-backed - More reliable than cron
- ✅ Built-in monitoring - Better visibility into job status
- ✅ Job chaining - Automatic OrderExecution → StockPrices flow
- ✅ Rails 8 native - Optimized performance and integration
Related Documentation
- Solid Queue Migration Guide - Technical migration details
- Heroku Deployment Guide - Deployment instructions
- Orders and Transactions - Business logic overview