319 lines
9.8 KiB
Markdown
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 |