fix: start archive scheduler in background thread when serving

This commit is contained in:
Jarian Cottingham 2026-07-08 02:45:50 +00:00
parent 60e99e521d
commit 2352e02fc9

View File

@ -11,7 +11,9 @@ import argparse
import atexit import atexit
import logging import logging
import os import os
import signal
import sys import sys
import threading
import time import time
from pathlib import Path from pathlib import Path
@ -166,18 +168,42 @@ def run_scheduler(interval_minutes: int, logger: logging.Logger, verbose: bool =
sys.exit(1) sys.exit(1)
def run_web_server(host: str, port: int, logger: logging.Logger, verbose: bool = False) -> None: def run_web_server(host: str, port: int, logger: logging.Logger, verbose: bool = False, interval_minutes: int = None) -> None:
"""Run Flask web server. """Run Flask web server with optional background scheduler.
Args: Args:
host: Host to bind to host: Host to bind to
port: Port to bind to port: Port to bind to
logger: Logger instance logger: Logger instance
verbose: If True, enable verbose logging verbose: If True, enable verbose logging
interval_minutes: If set, start background scheduler at this interval
""" """
logger.info("Starting web server") logger.info("Starting web server")
logger.info("=" * 60) 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: try:
if not (ARCHIVE_DIR / 'cache.db').exists(): if not (ARCHIVE_DIR / 'cache.db').exists():
logger.info("Database not found, initializing...") 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(): if not check_singlefile_available():
logger.warning("SingleFile CLI not available. Some features may not work.") 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("Web server starting on %s:%d", host, port)
logger.info("=" * 60) logger.info("=" * 60)
@ -230,8 +263,8 @@ Examples:
parser.add_argument( parser.add_argument(
'--interval', '--interval',
type=int, type=int,
default=60, default=None,
help='Run background scheduler with specified interval (minutes, default: 60)' help='Run background scheduler with specified interval (minutes). When used with --serve, runs in background thread (default: 60 min). Standalone blocks.'
) )
parser.add_argument( parser.add_argument(
@ -270,13 +303,14 @@ Examples:
if args.run: if args.run:
success = run_archive_once(logger, args.verbose) success = run_archive_once(logger, args.verbose)
sys.exit(0 if success else 1) sys.exit(0 if success else 1)
elif args.serve: 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: elif args.interval:
run_scheduler(args.interval, logger, args.verbose) run_scheduler(args.interval, logger, args.verbose)
else: else:
parser.print_help() parser.print_help()
sys.exit(1) sys.exit(1)