mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 10:13:32 -04:00 
			
		
		
		
	* add basic pre-commit file * add flake8 * add isort * add pep585-upgrade (typing upgrades) * use namespace for import * add mypy * update ci for backend * flake8 scope * fix version format * update makefile * disable strict option (temporary) * fix mypy issues * upgrade type hints (pre-commit) * add vscode typing check * add types to dev deps * remote container draft * update setup script * update compose version * run setup on create * dev containers update * remove unused pages * update setup tips * expose ports * Update pre-commit to include flask8-print (#1053) * Add in flake8-print to pre-commit * pin version of flake8-print * formatting * update getting strated docs * add mypy to pre-commit * purge .mypy_cache on clean * drop mypy Co-authored-by: zackbcom <zackbcom@users.noreply.github.com>
		
			
				
	
	
		
			96 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from pathlib import Path
 | |
| 
 | |
| from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
 | |
| from apscheduler.schedulers.background import BackgroundScheduler
 | |
| 
 | |
| from mealie.core import root_logger
 | |
| 
 | |
| from .scheduled_func import ScheduledFunc
 | |
| from .scheduler_registry import SchedulerRegistry
 | |
| 
 | |
| logger = root_logger.get_logger()
 | |
| 
 | |
| CWD = Path(__file__).parent
 | |
| 
 | |
| SCHEDULER_DB = CWD / ".scheduler.db"
 | |
| SCHEDULER_DATABASE = f"sqlite:///{SCHEDULER_DB}"
 | |
| 
 | |
| MINUTES_DAY = 1440
 | |
| MINUTES_15 = 15
 | |
| MINUTES_HOUR = 60
 | |
| 
 | |
| 
 | |
| class SchedulerService:
 | |
|     """
 | |
|     SchedulerService is a wrapper class around the APScheduler library. It is resonpseible for interacting with the scheduler
 | |
|     and scheduling events. This includes the interval events that are registered in the SchedulerRegistry as well as cron events
 | |
|     that are used for sending webhooks. In most cases, unless the the schedule is dynamic, events should be registered with the
 | |
|     SchedulerRegistry. See app.py for examples.
 | |
|     """
 | |
| 
 | |
|     _scheduler: BackgroundScheduler
 | |
| 
 | |
|     @staticmethod
 | |
|     def start():
 | |
|         # Preclean
 | |
|         SCHEDULER_DB.unlink(missing_ok=True)
 | |
| 
 | |
|         # Register Interval Jobs and Start Scheduler
 | |
|         SchedulerService._scheduler = BackgroundScheduler(jobstores={"default": SQLAlchemyJobStore(SCHEDULER_DATABASE)})
 | |
|         SchedulerService._scheduler.add_job(run_daily, "interval", minutes=MINUTES_DAY, id="Daily Interval Jobs")
 | |
|         SchedulerService._scheduler.add_job(run_hourly, "interval", minutes=MINUTES_HOUR, id="Hourly Interval Jobs")
 | |
|         SchedulerService._scheduler.add_job(run_minutely, "interval", minutes=MINUTES_15, id="Regular Interval Jobs")
 | |
|         SchedulerService._scheduler.start()
 | |
| 
 | |
|     @classmethod
 | |
|     @property
 | |
|     def scheduler(cls) -> BackgroundScheduler:
 | |
|         return SchedulerService._scheduler
 | |
| 
 | |
|     @staticmethod
 | |
|     def add_cron_job(job_func: ScheduledFunc):
 | |
|         SchedulerService.scheduler.add_job(  # type: ignore
 | |
|             job_func.callback,
 | |
|             trigger="cron",
 | |
|             name=job_func.id,
 | |
|             hour=job_func.hour,
 | |
|             minute=job_func.minutes,
 | |
|             max_instances=job_func.max_instances,  # type: ignore
 | |
|             replace_existing=job_func.replace_existing,
 | |
|             args=job_func.args,
 | |
|         )
 | |
| 
 | |
|     @staticmethod
 | |
|     def update_cron_job(job_func: ScheduledFunc):
 | |
|         SchedulerService.scheduler.reschedule_job(  # type: ignore
 | |
|             job_func.id,
 | |
|             trigger="cron",
 | |
|             hour=job_func.hour,
 | |
|             minute=job_func.minutes,
 | |
|         )
 | |
| 
 | |
| 
 | |
| def _scheduled_task_wrapper(callable):
 | |
|     try:
 | |
|         callable()
 | |
|     except Exception as e:
 | |
|         logger.error(f"Error in scheduled task func='{callable.__name__}': exception='{e}'")
 | |
| 
 | |
| 
 | |
| def run_daily():
 | |
|     logger.info("Running daily callbacks")
 | |
|     for func in SchedulerRegistry._daily:
 | |
|         _scheduled_task_wrapper(func)
 | |
| 
 | |
| 
 | |
| def run_hourly():
 | |
|     logger.info("Running hourly callbacks")
 | |
|     for func in SchedulerRegistry._hourly:
 | |
|         _scheduled_task_wrapper(func)
 | |
| 
 | |
| 
 | |
| def run_minutely():
 | |
|     logger.info("Running minutely callbacks")
 | |
|     for func in SchedulerRegistry._minutely:
 | |
|         _scheduled_task_wrapper(func)
 |