mirror of
https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git
synced 2025-03-17 20:14:39 +00:00
feature(backups): caps for autobackups
This commit is contained in:
parent
30b62c351a
commit
b2c7e8b73a
3 changed files with 75 additions and 0 deletions
|
@ -283,7 +283,10 @@ class Backups:
|
||||||
service_name,
|
service_name,
|
||||||
reason=reason,
|
reason=reason,
|
||||||
)
|
)
|
||||||
|
|
||||||
Backups._store_last_snapshot(service_name, snapshot)
|
Backups._store_last_snapshot(service_name, snapshot)
|
||||||
|
if reason == BackupReason.AUTO:
|
||||||
|
Backups._prune_auto_snaps(service)
|
||||||
service.post_restore()
|
service.post_restore()
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
Jobs.update(job, status=JobStatus.ERROR)
|
Jobs.update(job, status=JobStatus.ERROR)
|
||||||
|
@ -292,6 +295,40 @@ class Backups:
|
||||||
Jobs.update(job, status=JobStatus.FINISHED)
|
Jobs.update(job, status=JobStatus.FINISHED)
|
||||||
return snapshot
|
return snapshot
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _auto_snaps(service):
|
||||||
|
return [
|
||||||
|
snap
|
||||||
|
for snap in Backups.get_snapshots(service)
|
||||||
|
if snap.reason == BackupReason.AUTO
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _prune_auto_snaps(service) -> None:
|
||||||
|
max = Backups.max_auto_snapshots()
|
||||||
|
if max == -1:
|
||||||
|
return
|
||||||
|
|
||||||
|
auto_snaps = Backups._auto_snaps(service)
|
||||||
|
if len(auto_snaps) > max:
|
||||||
|
n_to_kill = len(auto_snaps) - max
|
||||||
|
sorted_snaps = sorted(auto_snaps, key=lambda s: s.created_at)
|
||||||
|
snaps_to_kill = sorted_snaps[:n_to_kill]
|
||||||
|
for snap in snaps_to_kill:
|
||||||
|
Backups.forget_snapshot(snap)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_max_auto_snapshots(value: int) -> None:
|
||||||
|
"""everything <=0 means unlimited"""
|
||||||
|
if value <= 0:
|
||||||
|
value = -1
|
||||||
|
Storage.set_max_auto_snapshots(value)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def max_auto_snapshots() -> int:
|
||||||
|
"""-1 means unlimited"""
|
||||||
|
return Storage.max_auto_snapshots()
|
||||||
|
|
||||||
# Restoring
|
# Restoring
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -26,6 +26,7 @@ REDIS_INITTED_CACHE = "backups:repo_initted"
|
||||||
REDIS_PROVIDER_KEY = "backups:provider"
|
REDIS_PROVIDER_KEY = "backups:provider"
|
||||||
REDIS_AUTOBACKUP_PERIOD_KEY = "backups:autobackup_period"
|
REDIS_AUTOBACKUP_PERIOD_KEY = "backups:autobackup_period"
|
||||||
|
|
||||||
|
REDIS_AUTOBACKUP_MAX_KEY = "backups:autobackup_cap"
|
||||||
|
|
||||||
redis = RedisPool().get_connection()
|
redis = RedisPool().get_connection()
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ class Storage:
|
||||||
redis.delete(REDIS_PROVIDER_KEY)
|
redis.delete(REDIS_PROVIDER_KEY)
|
||||||
redis.delete(REDIS_AUTOBACKUP_PERIOD_KEY)
|
redis.delete(REDIS_AUTOBACKUP_PERIOD_KEY)
|
||||||
redis.delete(REDIS_INITTED_CACHE)
|
redis.delete(REDIS_INITTED_CACHE)
|
||||||
|
redis.delete(REDIS_AUTOBACKUP_MAX_KEY)
|
||||||
|
|
||||||
prefixes_to_clean = [
|
prefixes_to_clean = [
|
||||||
REDIS_SNAPSHOTS_PREFIX,
|
REDIS_SNAPSHOTS_PREFIX,
|
||||||
|
@ -175,3 +177,14 @@ class Storage:
|
||||||
def mark_as_uninitted():
|
def mark_as_uninitted():
|
||||||
"""Marks the repository as initialized"""
|
"""Marks the repository as initialized"""
|
||||||
redis.delete(REDIS_INITTED_CACHE)
|
redis.delete(REDIS_INITTED_CACHE)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_max_auto_snapshots(value: int):
|
||||||
|
redis.set(REDIS_AUTOBACKUP_MAX_KEY, value)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def max_auto_snapshots():
|
||||||
|
if redis.exists(REDIS_AUTOBACKUP_MAX_KEY):
|
||||||
|
return int(redis.get(REDIS_AUTOBACKUP_MAX_KEY))
|
||||||
|
else:
|
||||||
|
return -1
|
||||||
|
|
|
@ -298,6 +298,31 @@ def test_backup_reasons(backups, dummy_service):
|
||||||
assert snaps[0].reason == BackupReason.AUTO
|
assert snaps[0].reason == BackupReason.AUTO
|
||||||
|
|
||||||
|
|
||||||
|
def test_too_many_auto(backups, dummy_service):
|
||||||
|
assert Backups.max_auto_snapshots() == -1
|
||||||
|
Backups.set_max_auto_snapshots(2)
|
||||||
|
assert Backups.max_auto_snapshots() == 2
|
||||||
|
|
||||||
|
snap = Backups.back_up(dummy_service, BackupReason.AUTO)
|
||||||
|
assert len(Backups.get_snapshots(dummy_service)) == 1
|
||||||
|
snap2 = Backups.back_up(dummy_service, BackupReason.AUTO)
|
||||||
|
assert len(Backups.get_snapshots(dummy_service)) == 2
|
||||||
|
snap3 = Backups.back_up(dummy_service, BackupReason.AUTO)
|
||||||
|
assert len(Backups.get_snapshots(dummy_service)) == 2
|
||||||
|
|
||||||
|
snaps = Backups.get_snapshots(dummy_service)
|
||||||
|
|
||||||
|
assert snap2 in snaps
|
||||||
|
assert snap3 in snaps
|
||||||
|
assert snap not in snaps
|
||||||
|
|
||||||
|
Backups.set_max_auto_snapshots(-1)
|
||||||
|
snap4 = Backups.back_up(dummy_service, BackupReason.AUTO)
|
||||||
|
snaps = Backups.get_snapshots(dummy_service)
|
||||||
|
assert len(snaps) == 3
|
||||||
|
assert snap4 in snaps
|
||||||
|
|
||||||
|
|
||||||
def folder_files(folder):
|
def folder_files(folder):
|
||||||
return [
|
return [
|
||||||
path.join(folder, filename)
|
path.join(folder, filename)
|
||||||
|
|
Loading…
Add table
Reference in a new issue