From 57912746557b5bb272dbc568a908196ec8c2589c Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Sat, 30 Oct 2021 23:42:06 +0200 Subject: [PATCH] #9 - use job scheduler to manually trigger cleanup --- src/logic/DatabaseCleanupService.py | 33 +++++++++++++++++++++++++ src/logic/database/Schemas.py | 20 +++++++++++++++ src/logic/routers/DatabaseRouter.py | 38 ++++++++++------------------- 3 files changed, 66 insertions(+), 25 deletions(-) create mode 100644 src/logic/DatabaseCleanupService.py diff --git a/src/logic/DatabaseCleanupService.py b/src/logic/DatabaseCleanupService.py new file mode 100644 index 0000000..cf654d1 --- /dev/null +++ b/src/logic/DatabaseCleanupService.py @@ -0,0 +1,33 @@ +from datetime import datetime +from typing import Dict + +from sqlalchemy.orm import Session + +from logic.database import Schemas, DatabaseInfoProvider +from logic.database.DatabaseCleaner import DatabaseCleaner +from logic.database.RetentionPolicy import RetentionPolicy + + +class DatabaseCleanupService: + def __init__(self, cleanupSettings: Dict): + self._cleanupSettings = cleanupSettings + + def cleanup(self, db: Session) -> Schemas.DatabaseCleanupInfo: + infoBefore = DatabaseInfoProvider.get_database_info(db) + + retentionPolicies = self._cleanupSettings['retentionPolicies'] + policies = [] + for item in retentionPolicies: + policies.append(RetentionPolicy(numberOfMeasurementsPerDay=item['numberOfMeasurementsPerDay'], + ageInDays=item['ageInDays'])) + + DatabaseCleaner(policies, self._cleanupSettings['forceBackupAfterCleanup']).clean(db, datetime.now().date()) + + infoAfter = DatabaseInfoProvider.get_database_info(db) + + deletedMeasurements = infoBefore.number_of_measurements - infoAfter.number_of_measurements + sizeFreed = infoBefore.size_on_disk_in_mb - infoAfter.size_on_disk_in_mb + infoDifference = Schemas.DatabaseInfo(number_of_measurements=deletedMeasurements, size_on_disk_in_mb=sizeFreed) + + return Schemas.DatabaseCleanupInfo(status=Schemas.DatabaseCleanupStatus.FINISHED, before=infoBefore, + after=infoAfter, difference=infoDifference) diff --git a/src/logic/database/Schemas.py b/src/logic/database/Schemas.py index c92ad06..961c4a1 100644 --- a/src/logic/database/Schemas.py +++ b/src/logic/database/Schemas.py @@ -134,3 +134,23 @@ class SensorValue(BaseModel): class MultipleMeasurements(BaseModel): deviceName: str sensors: List[SensorValue] + + +# ===== scheduled jobs ===== +class ScheduledJob(BaseModel): + job_id: str + run_frequency: str + next_run: str + + class Config: + schema_extra = { + 'example': { + 'job_id': 'my job id', + 'run_frequency': 'interval[0:05:00]', + 'next_run': '2021-09-30 22:12:09.397935+2:00' + } + } + + +class ScheduledJobs(BaseModel): + jobs: List[ScheduledJob] diff --git a/src/logic/routers/DatabaseRouter.py b/src/logic/routers/DatabaseRouter.py index 6783881..d96d617 100644 --- a/src/logic/routers/DatabaseRouter.py +++ b/src/logic/routers/DatabaseRouter.py @@ -1,12 +1,10 @@ -from datetime import datetime - -from fastapi import APIRouter, Depends +from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from Settings import SETTINGS +from logic.DatabaseCleanupService import DatabaseCleanupService from logic.Dependencies import get_database, check_api_key from logic.database import Schemas, DatabaseInfoProvider -from logic.database.DatabaseCleaner import DatabaseCleaner, RetentionPolicy router = APIRouter( prefix='/database', @@ -26,29 +24,19 @@ async def databaseInfo(db: Session = Depends(get_database)): response_model=Schemas.Status, dependencies=[Depends(check_api_key)]) async def databaseCleanup(db: Session = Depends(get_database)): - infoBefore = DatabaseInfoProvider.get_database_info(db) - - cleanupSettings = SETTINGS['database']['cleanup'] - - retentionPolicies = cleanupSettings['retentionPolicies'] - policies = [] - for item in retentionPolicies: - policies.append(RetentionPolicy(numberOfMeasurementsPerDay=item['numberOfMeasurementsPerDay'], - ageInDays=item['ageInDays'])) - - DatabaseCleaner(policies, cleanupSettings['forceBackupAfterCleanup']).clean(db, datetime.now().date()) - - infoAfter = DatabaseInfoProvider.get_database_info(db) - - deletedMeasurements = infoBefore.number_of_measurements - infoAfter.number_of_measurements - sizeFreed = infoBefore.size_on_disk_in_mb - infoAfter.size_on_disk_in_mb - infoDifference = Schemas.DatabaseInfo(number_of_measurements=deletedMeasurements, size_on_disk_in_mb=sizeFreed) + from logic import JobScheduler + cleanupService = DatabaseCleanupService(SETTINGS['database']['cleanup']) + try: + JobScheduler.SCHEDULER.run_manual_job(cleanupService.cleanup, args=[db]) + except JobScheduler.JobAlreadyRunningError as e: + raise HTTPException(status_code=400, detail=str(e)) - return Schemas.DatabaseCleanupInfo(before=infoBefore, after=infoAfter, difference=infoDifference) + return Schemas.Status(message='Successfully triggered database cleanup') @router.get('/databaseCleanup', - summary='Provides the status of the current database cleanup', - response_model=Schemas.DatabaseCleanupInfo) + summary='Provides the status of the all scheduled database cleanup jobs', + response_model=Schemas.ScheduledJobs) async def databaseCleanup(): - return Schemas.DatabaseCleanupInfo(status=Schemas.DatabaseCleanupStatus.UNDEFINED) + from logic import JobScheduler + return JobScheduler.SCHEDULER.get_scheduled_jobs() -- GitLab