""" APScheduler setup and configuration for background tasks. """ import functools from flask_apscheduler import APScheduler # Initialize scheduler globally scheduler = APScheduler() def job_wrapper(func, app_context, job_id): """ Wrapper to log job execution start and end. """ @functools.wraps(func) def wrapper(*args, **kwargs): app_context.logger.info(f"Job '{job_id}' starting...") try: result = func(*args, **kwargs) app_context.logger.info(f"Job '{job_id}' completed successfully.") return result except Exception as e: app_context.logger.error(f"Job '{job_id}' failed: {e}", exc_info=True) # Optionally re-raise or handle as needed raise return wrapper def init_scheduler(app): """ Initializes and starts the APScheduler with the Flask app. Registers scheduled jobs. """ if not scheduler.running: scheduler.init_app(app) # Import jobs here to avoid circular dependencies if jobs use app context or db from app.services.work_hours_service import calculate_and_store_real_work_hours # Register the job to calculate real work hours # Adjust interval as needed (e.g., every 10-15 minutes) # Ensure job_id is unique if you add more jobs if not app.config.get('TESTING', False): # Do not run scheduler during tests by default # Check if job already exists to prevent duplicates during reloads in debug mode if scheduler.get_job('calc_real_work_hours') is None: # Create a partial function that includes the app context # The original function expects the app object as its first argument # Explicitly set force_recalculate=False for scheduler to avoid double-counting wrapped_job_func = job_wrapper( functools.partial(calculate_and_store_real_work_hours, app, force_recalculate=False), \ app, \ 'calc_real_work_hours'\ ) scheduler.add_job( id='calc_real_work_hours', func=wrapped_job_func, trigger='interval', minutes=1, # Changed from 15 to 1 minute replace_existing=True ) app.logger.info("Scheduled job 'calc_real_work_hours' to run every 1 minute.") else: app.logger.info("Job 'calc_real_work_hours' already scheduled.") try: scheduler.start() app.logger.info("APScheduler started.") except Exception as e: app.logger.error(f"Failed to start APScheduler: {e}", exc_info=True) else: app.logger.info("APScheduler not started in TEST mode.") else: app.logger.info("APScheduler already running.")