feature(backups): stop services before backups

pull/35/head
Houkime 2023-07-12 16:43:26 +00:00 committed by Inex Code
parent a7427f3cb5
commit 40ad1b5ce4
2 changed files with 41 additions and 9 deletions

View File

@ -6,7 +6,7 @@ from typing import List, Optional
from selfprivacy_api.utils import ReadUserData, WriteUserData
from selfprivacy_api.services import get_service_by_id
from selfprivacy_api.services.service import Service
from selfprivacy_api.services.service import Service, ServiceStatus, StoppedService
from selfprivacy_api.jobs import Jobs, JobStatus, Job
@ -35,6 +35,18 @@ DEFAULT_JSON_PROVIDER = {
}
class NotDeadError(AssertionError):
def __init__(self, service: Service):
self.service_name = service.get_id()
def __str__(self):
return f"""
Service {self.service_name} should be either stopped or dead from an error before we back up.
Normally, this error is unreachable because we do try ensure this.
Apparently, not this time.
"""
class Backups:
"""A stateless controller class for backups"""
@ -193,13 +205,15 @@ class Backups:
Jobs.update(job, status=JobStatus.RUNNING)
try:
service.pre_backup()
snapshot = Backups.provider().backupper.start_backup(
folders,
tag,
)
Backups._store_last_snapshot(tag, snapshot)
service.post_restore()
with StoppedService(service):
Backups.assert_dead(service) # to be extra sure
service.pre_backup()
snapshot = Backups.provider().backupper.start_backup(
folders,
tag,
)
Backups._store_last_snapshot(tag, snapshot)
service.post_restore()
except Exception as e:
Jobs.update(job, status=JobStatus.ERROR)
raise e
@ -465,3 +479,11 @@ class Backups:
repo_id="",
)
Storage.store_provider(provider)
@staticmethod
def assert_dead(service: Service):
# if we backup the service that is failing to restore it to the
# previous snapshot, its status can be FAILED
# And obviously restoring a failed service is the moun route
if service.get_status() not in [ServiceStatus.INACTIVE, ServiceStatus.FAILED]:
raise NotDeadError(service)

View File

@ -303,7 +303,17 @@ def test_snapshots_by_id(backups, dummy_service):
assert Backups.get_snapshot_by_id(snap2.id).id == snap2.id
def test_backup_service_task(backups, dummy_service):
@pytest.fixture(params=["instant_server_stop", "delayed_server_stop"])
def simulated_service_stopping_delay(request) -> float:
if request.param == "instant_server_stop":
return 0.0
else:
return 0.3
def test_backup_service_task(backups, dummy_service, simulated_service_stopping_delay):
dummy_service.set_delay(simulated_service_stopping_delay)
handle = start_backup(dummy_service)
handle(blocking=True)