Files
BDFR_Web/web_interface/SCHEDULED_DOWNLOADS.md
T

319 lines
9.8 KiB
Markdown

# Scheduled Downloads Feature
## Overview
The BDFR Web Interface now supports scheduled downloads, allowing users to configure downloads that run automatically on a daily basis. This feature is designed to work seamlessly in Docker containers and ensures sequential execution to prevent system overload.
## Features
### 1. **Daily Scheduling**
- Tasks run once per day at a user-specified time
- Time is specified in the user's local timezone and automatically converted to UTC for container execution
- Automatically sets `time_filter="day"` to only download content from the last 24 hours
- Always enables `no_dupes=True` to avoid re-downloading existing content
### 2. **Sequential Execution**
- Tasks are processed one at a time through a queue system
- Manual "Run Now" tasks have priority over scheduled tasks
- Queue status is displayed in real-time
### 3. **Persistent Storage**
- SQLite database stores task configurations
- APScheduler job store ensures tasks persist across container restarts
- Execution history tracked for each task
### 4. **Full Task Management**
- Create, enable/disable, and delete scheduled tasks
- Run tasks manually on-demand
- View last run and next scheduled run times
## Architecture
### Backend Components
#### 1. **Database Models** (`web_interface/app/models.py`)
- `ScheduledTask`: Stores task configuration
- Fields: name, source (subreddit/user), schedule, timezone, etc.
- Automatically sets time_filter="day" and no_dupes=True
- `TaskExecutionHistory`: Tracks each execution
- Fields: task_id, status, items downloaded, errors, etc.
#### 2. **Task Queue** (`web_interface/app/task_queue.py`)
- `TaskQueue` class manages sequential execution
- Priority queue: 0=scheduled, 1=manual
- Blocks until each download completes before starting the next
- Thread-safe using asyncio
#### 3. **Scheduler Service** (`web_interface/app/scheduler.py`)
- APScheduler with SQLAlchemy job store for persistence
- Functions:
- `schedule_task()`: Creates cron job
- `queue_scheduled_task()`: Adds task to queue (called by scheduler)
- `execute_scheduled_task()`: Executes download and waits for completion
- `wait_for_download_completion()`: Polls every 5 seconds until done
#### 4. **API Endpoints** (`web_interface/app/scheduled_tasks.py`)
```
POST /api/scheduled-tasks - Create task
GET /api/scheduled-tasks - List all tasks
GET /api/scheduled-tasks/{id} - Get specific task
PUT /api/scheduled-tasks/{id} - Update task
DELETE /api/scheduled-tasks/{id} - Delete task
POST /api/scheduled-tasks/{id}/toggle - Enable/disable
POST /api/scheduled-tasks/{id}/run-now - Queue immediately
GET /api/scheduled-tasks/{id}/history - Execution history
GET /api/scheduled-tasks/queue/status - Queue status
```
### Frontend Components
#### 1. **HTML** (`web_interface/templates/index.html`)
- "Run Daily" checkbox in Advanced Options
- Schedule configuration fields (task name, run time)
- Scheduled Downloads section with task cards
- Queue status badge
#### 2. **JavaScript** (`web_interface/static/js/app.js`)
- `loadScheduledTasks()`: Fetches and renders tasks
- `createScheduledTask()`: Creates new scheduled task
- `toggleTask()`, `deleteTask()`, `runTaskNow()`: Task management
- `updateQueueStatus()`: Polls queue every 10 seconds
- Auto-detects browser timezone via `Intl.DateTimeFormat()`
#### 3. **CSS** (`web_interface/static/css/style.css`)
- Task card styling with hover effects
- Status badges (enabled/disabled)
- Schedule options panel
- Queue status badge
## Usage Guide
### Creating a Scheduled Download
1. **Configure Download Settings**
- Select download mode (Download/Archive/Clone)
- Choose source type (Subreddit/User)
- Enter source name
- Set limit, sort, and other options
2. **Enable Scheduling**
- Check "Run Daily" in Advanced Options
- Enter a task name (e.g., "Daily Python Posts")
- Select run time (24-hour format, in your local timezone)
3. **Submit**
- Click "Start Download" to create the scheduled task
- Task appears in the Scheduled Downloads section
- First run scheduled for the specified time
### Managing Scheduled Tasks
Each task card shows:
- Task name and source
- Download mode
- Schedule (daily at X time)
- Last run and next run times
- Status (Enabled/Disabled)
**Actions:**
- **Disable/Enable**: Toggle task on/off without deleting
- **Run Now**: Add task to queue immediately (higher priority)
- **Delete**: Remove task permanently
### Queue System
- Queue status badge shows number of tasks waiting
- Tasks execute one at a time to prevent overload
- Manual "Run Now" tasks have priority over scheduled tasks
- Download progress appears in Progress section
## Docker Deployment
### Volume Mounts Required
```yaml
volumes:
- ./downloads:/downloads # Downloaded files
- ./data:/app/data # Database and job store
```
### Database Location
- SQLite: `/app/data/scheduled_tasks.db`
- APScheduler job store: Same database
### Timezone Handling
- User specifies time in their local timezone
- Frontend auto-detects timezone via JavaScript
- Backend converts to UTC for container execution
- Cron jobs run at correct local time regardless of container timezone
## Technical Details
### Sequential Execution Flow
1. APScheduler triggers at scheduled time
2. Scheduler calls `queue_scheduled_task(task_id)`
3. Task added to queue with priority 0
4. Queue worker picks up task
5. `execute_scheduled_task()` called
6. Downloads via existing BDFR API
7. `wait_for_download_completion()` polls every 5s
8. Once complete, queue processes next task
9. Execution history recorded
### Time Filter Logic
For scheduled tasks:
- `time_filter` is automatically set to "day"
- This filters Reddit API to only return posts from last 24 hours
- Combined with daily scheduling, ensures only new content downloaded
- Prevents re-downloading old content
### Duplicate Prevention
For scheduled tasks:
- `no_dupes` is automatically enabled
- Uses existing BDFR duplicate detection
- Checks file hashes or URLs (depending on simple_check setting)
- Skips files that already exist
## Testing Checklist
### Basic Functionality
- [ ] Create scheduled task via "Run Daily" checkbox
- [ ] Task appears in Scheduled Downloads section
- [ ] Task name, source, and schedule displayed correctly
- [ ] Enable/disable toggle works
- [ ] Delete removes task
### Execution
- [ ] Manual "Run Now" triggers download immediately
- [ ] Download progress appears in Progress section
- [ ] Task completes successfully
- [ ] Execution history recorded
### Sequential Processing
- [ ] Queue multiple tasks via "Run Now"
- [ ] Tasks execute one at a time (not concurrent)
- [ ] Queue badge shows correct count
- [ ] Manual tasks execute before scheduled tasks
### Persistence
- [ ] Restart container/server
- [ ] Tasks still present after restart
- [ ] Scheduled jobs still execute at correct time
- [ ] Execution history preserved
### Timezone Handling
- [ ] Create task with different timezone
- [ ] Task runs at correct local time
- [ ] Next run time displays in user's timezone
### Edge Cases
- [ ] Create task with invalid source name
- [ ] Disable task, verify it doesn't run
- [ ] Enable disabled task
- [ ] Delete task while it's running
- [ ] Run same task multiple times quickly
## Troubleshooting
### Tasks Not Running
1. Check container logs for scheduler errors
2. Verify `/app/data` volume is mounted
3. Check database file permissions
4. Verify APScheduler is running (`scheduler.running()`)
### Queue Stuck
1. Check task_queue status in logs
2. Verify WebSocket connection for progress updates
3. Restart container to reset queue
### Timezone Issues
1. Verify browser timezone detection in DevTools
2. Check conversion in scheduler logs
3. Ensure container has correct UTC time
### Database Issues
1. Check `/app/data/scheduled_tasks.db` exists
2. Verify write permissions
3. Use SQLite browser to inspect tables
4. Check for migration errors in logs
## Future Enhancements
Potential improvements:
- [ ] Weekly scheduling option
- [ ] Custom time filters (last 3 days, last week, etc.)
- [ ] Email notifications on completion/failure
- [ ] Retry logic for failed tasks
- [ ] Task templates for quick setup
- [ ] Bulk operations (enable/disable multiple tasks)
- [ ] Advanced schedule expressions (cron syntax)
- [ ] Export/import task configurations
- [ ] Task execution statistics and charts
- [ ] Pause/resume queue
## API Examples
### Create Task
```bash
curl -X POST http://localhost:8000/api/scheduled-tasks \
-H "Content-Type: application/json" \
-d '{
"name": "Daily Python Posts",
"source_type": "subreddit",
"source_name": "python",
"download_mode": "download",
"limit": 50,
"sort": "hot",
"run_time": "02:00",
"timezone": "Pacific/Auckland",
"enabled": true
}'
```
### List Tasks
```bash
curl http://localhost:8000/api/scheduled-tasks
```
### Toggle Task
```bash
curl -X POST http://localhost:8000/api/scheduled-tasks/1/toggle
```
### Run Task Now
```bash
curl -X POST http://localhost:8000/api/scheduled-tasks/1/run-now
```
### Get Queue Status
```bash
curl http://localhost:8000/api/scheduled-tasks/queue/status
```
## Files Modified/Created
### Created:
- `web_interface/app/database.py` - Database configuration
- `web_interface/app/models.py` - ORM models
- `web_interface/app/task_queue.py` - Queue manager
- `web_interface/app/scheduler.py` - Scheduler service
- `web_interface/app/scheduled_tasks.py` - API endpoints
- `web_interface/SCHEDULED_DOWNLOADS.md` - This file
### Modified:
- `web_interface/requirements.txt` - Added dependencies
- `web_interface/app/main.py` - Integrated scheduler
- `web_interface/templates/index.html` - Added UI elements
- `web_interface/static/js/app.js` - Added JavaScript functions
- `web_interface/static/css/style.css` - Added styles
## Dependencies Added
```
sqlalchemy>=2.0.0
alembic>=1.12.0
apscheduler>=3.10.0
pytz>=2023.3