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