275 lines
7.6 KiB
Markdown
275 lines
7.6 KiB
Markdown
# 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
|
|
|
|
1. **OrderExecutionJob** - Executes pending stock orders (both buy and sell) at 1:00 AM ET weekdays only (Monday-Friday)
|
|
2. **StockPricesUpdateJob** - Updates stock prices from Alpha Vantage API (automatically triggered after OrderExecutionJob)
|
|
3. **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`](../config/recurring.yml):
|
|
|
|
```yaml
|
|
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`](../config/queue.yml):
|
|
|
|
```yaml
|
|
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)
|
|
1. **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)
|
|
|
|
2. **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)
|
|
3. **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:
|
|
|
|
```bash
|
|
# Start worker in development
|
|
bin/jobs
|
|
|
|
# Or run in background
|
|
bin/jobs &
|
|
```
|
|
|
|
Test job scheduling:
|
|
```bash
|
|
# Test manual job execution
|
|
rails console
|
|
OrderExecutionJob.perform_later
|
|
SolidQueue::Job.count # Should show queued jobs
|
|
```
|
|
|
|
### Staging Deployment
|
|
|
|
#### Heroku
|
|
```bash
|
|
# 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:
|
|
|
|
```ini
|
|
# /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
|
|
```
|
|
|
|
```bash
|
|
# 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
|
|
|
|
1. **Database Access**: All job data is stored in PostgreSQL
|
|
2. **Active Worker Process**: Must have `bin/jobs` running
|
|
3. **API Access**: StockPricesUpdateJob requires Alpha Vantage API access
|
|
4. **Environment Variables**: `ALPHA_VANTAGE_API_KEY` must be set
|
|
|
|
### Database Tables
|
|
|
|
Solid Queue uses these database tables:
|
|
- `solid_queue_jobs` - Main job queue
|
|
- `solid_queue_ready_executions` - Jobs ready to run
|
|
- `solid_queue_recurring_executions` - Recurring job schedules
|
|
- `solid_queue_failed_executions` - Failed jobs for debugging
|
|
|
|
## Monitoring
|
|
|
|
### Job Status Monitoring
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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/jobs` process
|
|
- Heroku logs: `heroku logs --tail -a your-app-name`
|
|
|
|
## Manual Execution
|
|
|
|
For testing or emergency runs:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
1. **Jobs not running**:
|
|
- Check worker process is running (`bin/jobs`)
|
|
- Verify database connection
|
|
- Check `solid_queue_jobs` table exists
|
|
|
|
2. **Jobs failing**:
|
|
- Check `SolidQueue::FailedExecution.all` for error details
|
|
- Verify API keys are set (`ALPHA_VANTAGE_API_KEY`)
|
|
- Check database connectivity
|
|
|
|
3. **Recurring jobs not scheduling**:
|
|
- Verify `config/recurring.yml` syntax
|
|
- Check worker is running with recurring job support
|
|
- Confirm time zone settings
|
|
|
|
4. **Performance issues**:
|
|
- Adjust `JOB_CONCURRENCY` environment variable
|
|
- Monitor database table sizes
|
|
- Check API rate limits
|
|
|
|
### Debugging Commands
|
|
|
|
```bash
|
|
# 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](solid-queue-migration.md) - Technical migration details
|
|
- [Heroku Deployment Guide](heroku-deployment-solid-queue.md) - Deployment instructions
|
|
- [Orders and Transactions](orders-and-transactions.md) - Business logic overview |