move job scheduling to DB
This commit is contained in:
+1
-2
@@ -29,10 +29,9 @@ PORT=8080
|
||||
# Download settings
|
||||
# DOWNLOAD_PARALLEL_LIMIT: Max concurrent downloads
|
||||
# DOWNLOAD_RATE_LIMIT: Seconds between requests (to avoid rate limiting)
|
||||
# DEFAULT_CHECK_INTERVAL: Seconds between automatic checks for new content
|
||||
# Check interval is configured per-source in the web UI (Settings page)
|
||||
DOWNLOAD_PARALLEL_LIMIT=3
|
||||
DOWNLOAD_RATE_LIMIT=3.0
|
||||
DEFAULT_CHECK_INTERVAL=3600
|
||||
|
||||
# Logging level (DEBUG, INFO, WARNING, ERROR)
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
@@ -31,6 +31,29 @@ async def get_or_create_extension_api_key(session: AsyncSession) -> str:
|
||||
return new_key
|
||||
|
||||
|
||||
async def get_setting_value(session: AsyncSession, key: str, default=None):
|
||||
"""Get a setting value from the database, falling back to defaults.
|
||||
|
||||
Args:
|
||||
session: Database session
|
||||
key: Setting key (e.g., 'download.schedule_interval')
|
||||
default: Fallback if not in database or DEFAULT_SETTINGS
|
||||
|
||||
Returns:
|
||||
The setting value
|
||||
"""
|
||||
result = await session.execute(
|
||||
select(Setting).where(Setting.key == key)
|
||||
)
|
||||
setting = result.scalar()
|
||||
|
||||
if setting:
|
||||
return setting.value
|
||||
|
||||
# Fall back to DEFAULT_SETTINGS, then to provided default
|
||||
return DEFAULT_SETTINGS.get(key, default)
|
||||
|
||||
|
||||
@bp.route("", methods=["GET"])
|
||||
async def get_all_settings():
|
||||
"""Get all application settings."""
|
||||
|
||||
@@ -8,6 +8,7 @@ from sqlalchemy.orm import selectinload
|
||||
from app.models.source import Source
|
||||
from app.models.subscription import Subscription
|
||||
from app.tasks.downloads import download_source
|
||||
from app.api.settings import get_setting_value
|
||||
|
||||
bp = Blueprint("sources", __name__)
|
||||
|
||||
@@ -100,12 +101,17 @@ async def create_source():
|
||||
if existing.scalar():
|
||||
return jsonify({"error": "Source with this platform and URL already exists"}), 409
|
||||
|
||||
# Get default check interval from database settings
|
||||
default_interval = await get_setting_value(
|
||||
session, "download.schedule_interval", 3600
|
||||
)
|
||||
|
||||
source = Source(
|
||||
subscription_id=data["subscription_id"],
|
||||
platform=data["platform"],
|
||||
url=data["url"],
|
||||
enabled=data.get("enabled", True),
|
||||
check_interval=data.get("check_interval", 3600),
|
||||
check_interval=data.get("check_interval", default_interval),
|
||||
metadata_=data.get("metadata", {}),
|
||||
)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from sqlalchemy.orm import selectinload
|
||||
from app.models.subscription import Subscription
|
||||
from app.models.source import Source
|
||||
from app.tasks.downloads import download_source
|
||||
from app.api.settings import get_setting_value
|
||||
|
||||
bp = Blueprint("subscriptions", __name__)
|
||||
|
||||
@@ -85,6 +86,11 @@ async def create_subscription():
|
||||
metadata_=data.get("metadata", {}),
|
||||
)
|
||||
|
||||
# Get default check interval from database settings
|
||||
default_interval = await get_setting_value(
|
||||
session, "download.schedule_interval", 3600
|
||||
)
|
||||
|
||||
# Add sources if provided
|
||||
sources_data = data.get("sources", [])
|
||||
for source_data in sources_data:
|
||||
@@ -94,7 +100,7 @@ async def create_subscription():
|
||||
platform=source_data["platform"],
|
||||
url=source_data["url"],
|
||||
enabled=source_data.get("enabled", True),
|
||||
check_interval=source_data.get("check_interval", 3600),
|
||||
check_interval=source_data.get("check_interval", default_interval),
|
||||
metadata_=source_data.get("metadata", {}),
|
||||
)
|
||||
subscription.sources.append(source)
|
||||
@@ -254,12 +260,17 @@ async def add_source_to_subscription(subscription_id: int):
|
||||
# Store name before commit (attributes expire after commit)
|
||||
subscription_name = subscription.name
|
||||
|
||||
# Get default check interval from database settings
|
||||
default_interval = await get_setting_value(
|
||||
session, "download.schedule_interval", 3600
|
||||
)
|
||||
|
||||
source = Source(
|
||||
subscription_id=subscription_id,
|
||||
platform=data["platform"],
|
||||
url=data["url"],
|
||||
enabled=data.get("enabled", True),
|
||||
check_interval=data.get("check_interval", 3600),
|
||||
check_interval=data.get("check_interval", default_interval),
|
||||
metadata_=data.get("metadata", {}),
|
||||
)
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class Settings(BaseSettings):
|
||||
# Download settings
|
||||
download_parallel_limit: int = 3
|
||||
download_rate_limit: float = 3.0
|
||||
default_check_interval: int = 3600 # seconds
|
||||
# Note: check_interval is now per-source and stored in database
|
||||
|
||||
# Server
|
||||
host: str = "0.0.0.0"
|
||||
|
||||
@@ -28,10 +28,13 @@ celery_app.conf.update(
|
||||
)
|
||||
|
||||
# Celery Beat schedule for periodic tasks
|
||||
# Note: The scheduler runs frequently (every 60s) but only triggers downloads
|
||||
# for sources whose individual check_interval has elapsed. Per-source intervals
|
||||
# are stored in the database and can be configured via the UI.
|
||||
celery_app.conf.beat_schedule = {
|
||||
"check-sources-hourly": {
|
||||
"check-sources-scheduler": {
|
||||
"task": "app.tasks.downloads.scheduled_check",
|
||||
"schedule": settings.default_check_interval, # Default: every hour
|
||||
"schedule": 60, # Run every 60 seconds to check for due sources
|
||||
},
|
||||
"cleanup-old-downloads-daily": {
|
||||
"task": "app.tasks.downloads.cleanup_old_downloads",
|
||||
|
||||
@@ -22,7 +22,6 @@ services:
|
||||
- SECRET_KEY=${SECRET_KEY:-dev-secret-key-not-for-production}
|
||||
- DOWNLOAD_PARALLEL_LIMIT=${DOWNLOAD_PARALLEL_LIMIT:-3}
|
||||
- DOWNLOAD_RATE_LIMIT=${DOWNLOAD_RATE_LIMIT:-3.0}
|
||||
- DEFAULT_CHECK_INTERVAL=${DEFAULT_CHECK_INTERVAL:-3600}
|
||||
- LOG_LEVEL=DEBUG
|
||||
- DEBUG=true
|
||||
volumes:
|
||||
@@ -47,7 +46,6 @@ services:
|
||||
- SECRET_KEY=${SECRET_KEY:-dev-secret-key-not-for-production}
|
||||
- DOWNLOAD_PARALLEL_LIMIT=${DOWNLOAD_PARALLEL_LIMIT:-3}
|
||||
- DOWNLOAD_RATE_LIMIT=${DOWNLOAD_RATE_LIMIT:-3.0}
|
||||
- DEFAULT_CHECK_INTERVAL=${DEFAULT_CHECK_INTERVAL:-3600}
|
||||
- LOG_LEVEL=DEBUG
|
||||
- DEBUG=true
|
||||
volumes:
|
||||
|
||||
@@ -20,7 +20,6 @@ services:
|
||||
- SECRET_KEY=${SECRET_KEY}
|
||||
- DOWNLOAD_PARALLEL_LIMIT=${DOWNLOAD_PARALLEL_LIMIT:-3}
|
||||
- DOWNLOAD_RATE_LIMIT=${DOWNLOAD_RATE_LIMIT:-3.0}
|
||||
- DEFAULT_CHECK_INTERVAL=${DEFAULT_CHECK_INTERVAL:-3600}
|
||||
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
||||
volumes:
|
||||
- ${DATA_DOWNLOADS:-downloads}:/data/downloads
|
||||
@@ -43,7 +42,6 @@ services:
|
||||
- SECRET_KEY=${SECRET_KEY}
|
||||
- DOWNLOAD_PARALLEL_LIMIT=${DOWNLOAD_PARALLEL_LIMIT:-3}
|
||||
- DOWNLOAD_RATE_LIMIT=${DOWNLOAD_RATE_LIMIT:-3.0}
|
||||
- DEFAULT_CHECK_INTERVAL=${DEFAULT_CHECK_INTERVAL:-3600}
|
||||
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
||||
volumes:
|
||||
- ${DATA_DOWNLOADS:-downloads}:/data/downloads
|
||||
|
||||
Reference in New Issue
Block a user