Files
overub/core/backup_service.py
2025-12-21 17:12:32 +01:00

79 lines
3.0 KiB
Python

import asyncio
import contextlib
from typing import Optional
from core.logger import get_logger
from core.scheduler import ScheduleConfig, Scheduler
logger = get_logger("core.backup_service")
class BackupService:
def __init__(self, app: "OverUB") -> None:
self.app = app
cfg = app.config.get().get("backup", {})
self._auto = bool(cfg.get("auto", False))
schedule_time = cfg.get("schedule", "03:30")
self._scheduler = Scheduler(
ScheduleConfig(
time=schedule_time,
postpone_on_activity=bool(cfg.get("postpone_on_activity", True)),
max_downtime=int(cfg.get("max_downtime", 120)),
retry_failed=bool(cfg.get("retry_failed", True)),
retry_interval=int(cfg.get("retry_interval", 3600)),
)
)
self._interval = int(cfg.get("check_interval", 60))
self._scopes = cfg.get("scopes", ["core", "modules", "plugins"])
self._task: Optional[asyncio.Task] = None
def start(self) -> None:
if self._task and not self._task.done():
return
self._task = asyncio.create_task(self._run_loop())
async def stop(self) -> None:
if self._task:
self._task.cancel()
with contextlib.suppress(asyncio.CancelledError):
await self._task
async def _run_loop(self) -> None:
while True:
try:
self._refresh_config()
if self._auto and self._scheduler.should_run(self.app.last_activity):
await self._run_backup()
except Exception:
logger.exception("Scheduled backup failed")
self._scheduler.mark_failed()
self.app.update_service.record_event(
action="backup",
status="failed",
meta={"scopes": self._scopes},
)
await asyncio.sleep(self._interval)
async def _run_backup(self) -> None:
for scope in self._scopes:
self.app.backups.create(scope)
self._scheduler.mark_run()
self.app.update_service.record_event(
action="backup",
status="success",
meta={"scopes": self._scopes},
)
def _refresh_config(self) -> None:
cfg = self.app.config.get().get("backup", {})
self._auto = bool(cfg.get("auto", False))
schedule_time = cfg.get("schedule", self._scheduler.config.time)
self._scheduler.config.time = schedule_time
self._scheduler.config.postpone_on_activity = bool(cfg.get("postpone_on_activity", True))
self._scheduler.config.max_downtime = int(cfg.get("max_downtime", 120))
self._scheduler.config.retry_failed = bool(cfg.get("retry_failed", True))
self._scheduler.config.retry_interval = int(cfg.get("retry_interval", 3600))
self._interval = int(cfg.get("check_interval", self._interval))
self._scopes = cfg.get("scopes", self._scopes)