mirror of
https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git
synced 2024-11-22 12:11:26 +00:00
feature(backups): stop services before backups
This commit is contained in:
parent
326e3d3b0c
commit
7af7600599
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue