mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-06 07:53:11 -05: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)
|