diff --git a/run_archiver.py b/run_archiver.py index b558439..e3739a4 100644 --- a/run_archiver.py +++ b/run_archiver.py @@ -11,7 +11,9 @@ import argparse import atexit import logging import os +import signal import sys +import threading import time from pathlib import Path @@ -166,18 +168,42 @@ def run_scheduler(interval_minutes: int, logger: logging.Logger, verbose: bool = sys.exit(1) -def run_web_server(host: str, port: int, logger: logging.Logger, verbose: bool = False) -> None: - """Run Flask web server. +def run_web_server(host: str, port: int, logger: logging.Logger, verbose: bool = False, interval_minutes: int = None) -> None: + """Run Flask web server with optional background scheduler. Args: host: Host to bind to port: Port to bind to logger: Logger instance verbose: If True, enable verbose logging + interval_minutes: If set, start background scheduler at this interval """ logger.info("Starting web server") logger.info("=" * 60) + _scheduler_stopped = [False] + + def _start_scheduler(): + try: + init_db_rss() + initialize_storage() + start_scheduler(interval_minutes) + logger.info("Background scheduler started (every %d min)", interval_minutes) + logger.info("Running initial archive...") + scheduled_archive(logger) + logger.info("Initial archive complete") + except Exception as e: + logger.error("Scheduler thread failed: %s", str(e)) + finally: + _scheduler_stopped[0] = True + + def _shutdown_scheduler(signum=None, frame=None): + if not _scheduler_stopped[0]: + logger.info("Stopping scheduler...") + stop_scheduler() + logger.info("Scheduler stopped") + sys.exit(0) + try: if not (ARCHIVE_DIR / 'cache.db').exists(): logger.info("Database not found, initializing...") @@ -186,6 +212,13 @@ def run_web_server(host: str, port: int, logger: logging.Logger, verbose: bool = if not check_singlefile_available(): logger.warning("SingleFile CLI not available. Some features may not work.") + if interval_minutes: + logger.info("Starting background archive scheduler (interval: %d min)...", interval_minutes) + t = threading.Thread(target=_start_scheduler, daemon=True) + t.start() + signal.signal(signal.SIGINT, _shutdown_scheduler) + signal.signal(signal.SIGTERM, _shutdown_scheduler) + logger.info("Web server starting on %s:%d", host, port) logger.info("=" * 60) @@ -230,8 +263,8 @@ Examples: parser.add_argument( '--interval', type=int, - default=60, - help='Run background scheduler with specified interval (minutes, default: 60)' + default=None, + help='Run background scheduler with specified interval (minutes). When used with --serve, runs in background thread (default: 60 min). Standalone blocks.' ) parser.add_argument( @@ -270,13 +303,14 @@ Examples: if args.run: success = run_archive_once(logger, args.verbose) sys.exit(0 if success else 1) - + elif args.serve: - run_web_server(args.host, args.port, logger, args.verbose) - + interval = args.interval if args.interval else 60 + run_web_server(args.host, args.port, logger, args.verbose, interval_minutes=interval) + elif args.interval: run_scheduler(args.interval, logger, args.verbose) - + else: parser.print_help() sys.exit(1)