79 lines
3.0 KiB
Python
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)
|