diff --git a/settings-example.json b/settings-example.json index 7ad89b651a2664c13f704274b2122528a3ffdbde..b6b00b7cb642689a17c3361dd211b508809c44a3 100644 --- a/settings-example.json +++ b/settings-example.json @@ -32,7 +32,11 @@ "numberOfMeasurementsPerDay": 2, "ageInDays": 60 } - ] + ], + "automatic": { + "enable": true, + "cronSchedule": "0 0 * * 0" + } } }, "api": { diff --git a/src/StorageLeaf.py b/src/StorageLeaf.py index f746f23162fc7ca19f888a78eabb4769231265c7..8b432ca1702796eec33c06753deb2de91d0c2c4e 100644 --- a/src/StorageLeaf.py +++ b/src/StorageLeaf.py @@ -1,8 +1,8 @@ -import json import os import uvicorn from TheCodeLabs_BaseUtils.DefaultLogger import DefaultLogger +from apscheduler.triggers.cron import CronTrigger from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html @@ -10,6 +10,8 @@ from starlette.responses import RedirectResponse, FileResponse from Settings import SETTINGS, VERSION from logic import Constants +from logic.DatabaseCleanupService import DatabaseCleanupService +from logic.Dependencies import get_database from logic.DiscoveryService import DiscoveryService from logic.database import Models from logic.database.Database import engine @@ -20,7 +22,6 @@ LOGGER = DefaultLogger().create_logger_if_not_exists(Constants.APP_NAME) DATABASE_SETTINGS = SETTINGS['database'] - # create database tables Models.Base.metadata.create_all(bind=engine) @@ -62,6 +63,21 @@ def overridden_redoc(): redoc_favicon_url=app.url_path_for('favicon')) +@app.on_event("startup") +async def startup_event(): + cleanupSettings = SETTINGS['database']['cleanup'] + if cleanupSettings['automatic']['enable']: + cleanupService = DatabaseCleanupService(cleanupSettings) + + try: + cronTrigger = CronTrigger.from_crontab(cleanupSettings['automatic']['cronSchedule']) + except ValueError as e: + raise ValueError(f'Invalid syntax for settings option "cronSchedule": {str(e)}') from e + + from logic import JobScheduler + JobScheduler.SCHEDULER.schedule_automatic_job(cleanupService.cleanup, [next(get_database())], cronTrigger) + + app.include_router(GeneralRouter.router) app.include_router(DatabaseRouter.router) app.include_router(DeviceRouter.router) diff --git a/src/logic/JobScheduler.py b/src/logic/JobScheduler.py index fc4548af147dcba29fe82bb5f91bb4b615cb14a1..ade63782a31cd05bc6f1894fa1af5f0d95bf187e 100644 --- a/src/logic/JobScheduler.py +++ b/src/logic/JobScheduler.py @@ -5,6 +5,7 @@ from typing import Callable, List import pytz from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR, JobExecutionEvent from apscheduler.schedulers.asyncio import AsyncIOScheduler +from apscheduler.triggers.cron import CronTrigger from logic import Constants from logic.database import Schemas @@ -45,10 +46,9 @@ class JobScheduler: else: LOGGER.debug(f'Successfully finished job "{event.job_id}" (retval: {event.retval})') - def schedule_automatic_job(self, func: Callable, args: List, interval_in_minutes: int): + def schedule_automatic_job(self, func: Callable, args: List, cronTrigger: CronTrigger): self._jobAutomatic = self._jobAutomatic.modify(func=func, args=args) - self._jobAutomatic = self._jobAutomatic.reschedule(trigger='interval', minutes=interval_in_minutes, - timezone=TIMEZONE) + self._jobAutomatic = self._jobAutomatic.reschedule(trigger=cronTrigger, timezone=TIMEZONE) self._jobStatus[self.ID_AUTO] = self.STATE_RUNNING def run_manual_job(self, func: Callable, args: List): @@ -79,4 +79,4 @@ class JobAlreadyRunningError(Exception): pass -SCHEDULER = JobScheduler() +SCHEDULER: JobScheduler = JobScheduler() diff --git a/src/logic/routers/DatabaseRouter.py b/src/logic/routers/DatabaseRouter.py index d96d617bc2c639a5c8e446bdcd1ca1f559c00acf..c46fe106923cd95e7c8844e85791cbcc46c0529e 100644 --- a/src/logic/routers/DatabaseRouter.py +++ b/src/logic/routers/DatabaseRouter.py @@ -37,6 +37,6 @@ async def databaseCleanup(db: Session = Depends(get_database)): @router.get('/databaseCleanup', summary='Provides the status of the all scheduled database cleanup jobs', response_model=Schemas.ScheduledJobs) -async def databaseCleanup(): +async def getStatus(): from logic import JobScheduler return JobScheduler.SCHEDULER.get_scheduled_jobs()