feature(backups): caps for autobackups
continuous-integration/drone/push Build is failing Details

pull/56/head
Houkime 2023-08-21 12:45:31 +00:00
parent 30b62c351a
commit b2c7e8b73a
3 changed files with 75 additions and 0 deletions

View File

@ -283,7 +283,10 @@ class Backups:
service_name,
reason=reason,
)
Backups._store_last_snapshot(service_name, snapshot)
if reason == BackupReason.AUTO:
Backups._prune_auto_snaps(service)
service.post_restore()
except Exception as error:
Jobs.update(job, status=JobStatus.ERROR)
@ -292,6 +295,40 @@ class Backups:
Jobs.update(job, status=JobStatus.FINISHED)
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
@staticmethod

View File

@ -26,6 +26,7 @@ REDIS_INITTED_CACHE = "backups:repo_initted"
REDIS_PROVIDER_KEY = "backups:provider"
REDIS_AUTOBACKUP_PERIOD_KEY = "backups:autobackup_period"
REDIS_AUTOBACKUP_MAX_KEY = "backups:autobackup_cap"
redis = RedisPool().get_connection()
@ -39,6 +40,7 @@ class Storage:
redis.delete(REDIS_PROVIDER_KEY)
redis.delete(REDIS_AUTOBACKUP_PERIOD_KEY)
redis.delete(REDIS_INITTED_CACHE)
redis.delete(REDIS_AUTOBACKUP_MAX_KEY)
prefixes_to_clean = [
REDIS_SNAPSHOTS_PREFIX,
@ -175,3 +177,14 @@ class Storage:
def mark_as_uninitted():
"""Marks the repository as initialized"""
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

View File

@ -298,6 +298,31 @@ def test_backup_reasons(backups, dummy_service):
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):
return [
path.join(folder, filename)