fix(backups): simplify autobackups to avoid deadlocks

pull/97/head
Houkime 2024-02-23 18:16:25 +00:00
parent e16f4499f8
commit 742bb239e7
2 changed files with 38 additions and 8 deletions

View File

@ -3,7 +3,7 @@ from typing import Optional, List
from selfprivacy_api.models.backup.snapshot import Snapshot from selfprivacy_api.models.backup.snapshot import Snapshot
from selfprivacy_api.jobs import Jobs, Job, JobStatus from selfprivacy_api.jobs import Jobs, Job, JobStatus
from selfprivacy_api.services.service import Service from selfprivacy_api.services.service import Service
from selfprivacy_api.services import get_service_by_id from selfprivacy_api.services import get_service_by_id, get_all_services
def job_type_prefix(service: Service) -> str: def job_type_prefix(service: Service) -> str:
@ -14,6 +14,10 @@ def backup_job_type(service: Service) -> str:
return f"{job_type_prefix(service)}.backup" return f"{job_type_prefix(service)}.backup"
def autobackup_job_type() -> str:
return f"backups.autobackup"
def restore_job_type(service: Service) -> str: def restore_job_type(service: Service) -> str:
return f"{job_type_prefix(service)}.restore" return f"{job_type_prefix(service)}.restore"
@ -36,6 +40,17 @@ def is_something_running_for(service: Service) -> bool:
return len(running_jobs) != 0 return len(running_jobs) != 0
def add_autobackup_job(services: List[Service]) -> Job:
service_names = [s.get_display_name() for s in services]
pretty_service_list: str = ", ".join(service_names)
job = Jobs.add(
type_id=autobackup_job_type(),
name=f"Automatic backup",
description=f"Scheduled backup for services : {pretty_service_list}",
)
return job
def add_backup_job(service: Service) -> Job: def add_backup_job(service: Service) -> Job:
if is_something_running_for(service): if is_something_running_for(service):
message = ( message = (

View File

@ -15,6 +15,7 @@ from huey import crontab
from selfprivacy_api.services.service import Service from selfprivacy_api.services.service import Service
from selfprivacy_api.services import get_service_by_id from selfprivacy_api.services import get_service_by_id
from selfprivacy_api.backup import Backups from selfprivacy_api.backup import Backups
from selfprivacy_api.backup.jobs import add_autobackup_job
from selfprivacy_api.jobs import Jobs, JobStatus, Job from selfprivacy_api.jobs import Jobs, JobStatus, Job
@ -72,26 +73,40 @@ def restore_snapshot(
return True return True
def do_autobackup(): def do_autobackup() -> None:
""" """
Body of autobackup task, broken out to test it Body of autobackup task, broken out to test it
For some reason, we cannot launch periodic huey tasks For some reason, we cannot launch periodic huey tasks
inside tests inside tests
""" """
time = datetime.utcnow().replace(tzinfo=timezone.utc) time = datetime.utcnow().replace(tzinfo=timezone.utc)
for service in Backups.services_to_back_up(time): services_to_back_up = Backups.services_to_back_up(time)
handle = start_backup(service.get_id(), BackupReason.AUTO) job = add_autobackup_job(services_to_back_up)
# To be on safe side, we do not do it in parallel
handle(blocking=True) progress_per_service = 100 // len(services_to_back_up)
progress = 0
Jobs.update(job, JobStatus.RUNNING, progress=progress)
for service in services_to_back_up:
try:
Backups.back_up(service, BackupReason.AUTO)
except Exception as error:
Jobs.update(
job,
status=JobStatus.ERROR,
error=type(error).__name__ + ": " + str(error),
)
return
progress = progress + progress_per_service
Jobs.update(job, JobStatus.RUNNING, progress=progress)
@huey.periodic_task(validate_datetime=validate_datetime) @huey.periodic_task(validate_datetime=validate_datetime)
def automatic_backup() -> bool: def automatic_backup() -> None:
""" """
The worker periodic task that starts the automatic backup process. The worker periodic task that starts the automatic backup process.
""" """
do_autobackup() do_autobackup()
return True
@huey.periodic_task(crontab(hour="*/" + str(SNAPSHOT_CACHE_TTL_HOURS))) @huey.periodic_task(crontab(hour="*/" + str(SNAPSHOT_CACHE_TTL_HOURS)))