backend/worker.py
Rama master · réplica de lectura del repositorio original.
"""RQ worker entry point for Sublarr background jobs.
Start this process alongside the main Flask app to enable persistent,
Redis-backed job queuing. Each job runs inside a Flask application context
so that db.session, config, and all Flask extensions are available.
Usage:
python worker.py
Configuration via environment variables (same as the main app):
SUBLARR_REDIS_URL Redis connection URL (required)
SUBLARR_QUEUE_NAME Queue name (default: sublarr)
Docker:
Use docker-compose.redis.yml which configures the rq-worker service.
Scale workers with:
docker compose -f docker-compose.redis.yml up -d --scale rq-worker=N
"""
import logging
import os
import sys
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger(__name__)
class _AppContextWorker:
"""Mixin that pushes a Flask app context around every RQ job.
Defined at module level so it is picklable (required by RQ).
"""
_app = None
@classmethod
def set_app(cls, app):
cls._app = app
def perform_job(self, job, queue, *args, **kwargs):
if self._app is not None:
with self._app.app_context():
return super().perform_job(job, queue, *args, **kwargs)
return super().perform_job(job, queue, *args, **kwargs)
def main():
from app import create_app
try:
from redis import Redis
from rq import Queue, Worker
except ImportError as exc:
logger.error("redis and rq packages are required: %s", exc)
sys.exit(1)
redis_url = os.environ.get("SUBLARR_REDIS_URL", "")
if not redis_url:
# Fall back to Pydantic settings so the same env var works
try:
from config import get_settings
redis_url = get_settings().redis_url
except Exception:
logger.debug("Could not read the Redis URL from the settings", exc_info=True)
if not redis_url:
logger.error(
"SUBLARR_REDIS_URL is not set. Set it to a Redis connection URL, "
"e.g. redis://localhost:6379/0"
)
sys.exit(1)
queue_name = os.environ.get("SUBLARR_QUEUE_NAME", "sublarr")
app = create_app()
try:
redis_conn = Redis.from_url(redis_url, socket_connect_timeout=10)
redis_conn.ping()
except Exception as exc:
logger.error("Cannot connect to Redis at %s: %s", redis_url, exc)
sys.exit(1)
# Build a Worker subclass with app context support
class AppContextWorker(_AppContextWorker, Worker):
pass
AppContextWorker.set_app(app)
queues = [Queue(queue_name, connection=redis_conn)]
worker = AppContextWorker(queues, connection=redis_conn)
logger.info("Sublarr RQ worker started — queue=%s redis=%s", queue_name, redis_url)
worker.work(with_scheduler=False)
if __name__ == "__main__":
main()