feat(UI): added docker image and config
This commit is contained in:
@@ -0,0 +1,319 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user