feat(api): add volume backup schedule delete endpoints

Expose DELETE for application, database, and service storage backup
schedules (with OpenAPI docs), reject storage deletes while schedules
exist, skip retention cleanup when no limits are set, and remove S3
archives using the execution’s S3 storage.
This commit is contained in:
Andras Bacsai committed 2026-07-16 21:44:48 +02:00
1 parent fab012b5c8
commit 28f8867567
11 files changed
+548 -16

No files matched your search

+28 -13
View File
@@ -334,25 +334,35 @@ class VolumeBackupJob implements ShouldBeEncrypted, ShouldQueue
private function removeExpiredBackups(Server $server): void
{
$localExecutions = $this->backup->executions()
->where('status', 'success')
->where('local_storage_deleted', false)
->get();
$localExecutions = $this->executionsOutsideRetention(
$localExecutions,
if ($this->hasRetentionLimits(
$this->backup->retention_amount_locally,
$this->backup->retention_days_locally,
$this->backup->retention_max_storage_locally,
);
)) {
$localExecutions = $this->backup->executions()
->where('status', 'success')
->where('local_storage_deleted', false)
->get();
$localExecutions = $this->executionsOutsideRetention(
$localExecutions,
$this->backup->retention_amount_locally,
$this->backup->retention_days_locally,
$this->backup->retention_max_storage_locally,
);
$filenames = $localExecutions->pluck('filename')->filter()->all();
if ($filenames !== []) {
deleteBackupsLocally($filenames, $server, throwError: true);
$this->backup->executions()->whereKey($localExecutions->pluck('id')->all())
->update(['local_storage_deleted' => true]);
$filenames = $localExecutions->pluck('filename')->filter()->all();
if ($filenames !== []) {
deleteBackupsLocally($filenames, $server, throwError: true);
$this->backup->executions()->whereKey($localExecutions->pluck('id')->all())
->update(['local_storage_deleted' => true]);
}
}
if ($this->backup->save_s3 && $this->backup->s3) {
if ($this->backup->save_s3 && $this->backup->s3 && $this->hasRetentionLimits(
$this->backup->retention_amount_s3,
$this->backup->retention_days_s3,
$this->backup->retention_max_storage_s3,
)) {
$s3Executions = $this->backup->executions()
->with('s3')
->where('status', 'success')
@@ -389,6 +399,11 @@ class VolumeBackupJob implements ShouldBeEncrypted, ShouldQueue
->delete();
}
private function hasRetentionLimits(int $amount, int $days, float $maxStorageGb): bool
{
return $amount > 0 || $days > 0 || $maxStorageGb > 0;
}
private function executionsOutsideRetention(Collection $executions, int $amount, int $days, float $maxStorageGb): Collection
{
if ($amount === 0 && $days === 0 && $maxStorageGb == 0) {