mirror of
https://github.com/immich-app/immich.git
synced 2025-07-31 15:08:44 -04:00
fix: handle cleanup of new backups alongside old backups (#20402)
This commit is contained in:
parent
2a005629a0
commit
a0fa7318ed
@ -1,3 +1,4 @@
|
|||||||
|
import { DateTime } from 'luxon';
|
||||||
import { PassThrough } from 'node:stream';
|
import { PassThrough } from 'node:stream';
|
||||||
import { defaults, SystemConfig } from 'src/config';
|
import { defaults, SystemConfig } from 'src/config';
|
||||||
import { StorageCore } from 'src/cores/storage.core';
|
import { StorageCore } from 'src/cores/storage.core';
|
||||||
@ -90,18 +91,23 @@ describe(BackupService.name, () => {
|
|||||||
|
|
||||||
it('should remove failed backup files', async () => {
|
it('should remove failed backup files', async () => {
|
||||||
mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.backupEnabled);
|
mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.backupEnabled);
|
||||||
|
//`immich-db-backup-${DateTime.now().toFormat("yyyyLLdd'T'HHmmss")}-v${serverVersion.toString()}-pg${databaseVersion.split(' ')[0]}.sql.gz.tmp`,
|
||||||
mocks.storage.readdir.mockResolvedValue([
|
mocks.storage.readdir.mockResolvedValue([
|
||||||
'immich-db-backup-123.sql.gz.tmp',
|
'immich-db-backup-123.sql.gz.tmp',
|
||||||
'immich-db-backup-234.sql.gz',
|
`immich-db-backup-${DateTime.fromISO('2025-07-25T11:02:16Z').toFormat("yyyyLLdd'T'HHmmss")}-v1.234.5-pg14.5.sql.gz.tmp`,
|
||||||
'immich-db-backup-345.sql.gz.tmp',
|
`immich-db-backup-${DateTime.fromISO('2025-07-27T11:01:16Z').toFormat("yyyyLLdd'T'HHmmss")}-v1.234.5-pg14.5.sql.gz`,
|
||||||
|
`immich-db-backup-${DateTime.fromISO('2025-07-29T11:01:16Z').toFormat("yyyyLLdd'T'HHmmss")}-v1.234.5-pg14.5.sql.gz.tmp`,
|
||||||
]);
|
]);
|
||||||
await sut.cleanupDatabaseBackups();
|
await sut.cleanupDatabaseBackups();
|
||||||
expect(mocks.storage.unlink).toHaveBeenCalledTimes(2);
|
expect(mocks.storage.unlink).toHaveBeenCalledTimes(3);
|
||||||
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
||||||
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-123.sql.gz.tmp`,
|
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-123.sql.gz.tmp`,
|
||||||
);
|
);
|
||||||
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
||||||
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-345.sql.gz.tmp`,
|
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-20250725T110216-v1.234.5-pg14.5.sql.gz.tmp`,
|
||||||
|
);
|
||||||
|
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
||||||
|
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-20250729T110116-v1.234.5-pg14.5.sql.gz.tmp`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -118,17 +124,21 @@ describe(BackupService.name, () => {
|
|||||||
it('should remove old backup files over keepLastAmount and failed backups', async () => {
|
it('should remove old backup files over keepLastAmount and failed backups', async () => {
|
||||||
mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.backupEnabled);
|
mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.backupEnabled);
|
||||||
mocks.storage.readdir.mockResolvedValue([
|
mocks.storage.readdir.mockResolvedValue([
|
||||||
'immich-db-backup-1.sql.gz.tmp',
|
`immich-db-backup-${DateTime.fromISO('2025-07-25T11:02:16Z').toFormat("yyyyLLdd'T'HHmmss")}-v1.234.5-pg14.5.sql.gz.tmp`,
|
||||||
'immich-db-backup-2.sql.gz',
|
`immich-db-backup-${DateTime.fromISO('2025-07-27T11:01:16Z').toFormat("yyyyLLdd'T'HHmmss")}-v1.234.5-pg14.5.sql.gz`,
|
||||||
'immich-db-backup-3.sql.gz',
|
'immich-db-backup-1753789649000.sql.gz',
|
||||||
|
`immich-db-backup-${DateTime.fromISO('2025-07-29T11:01:16Z').toFormat("yyyyLLdd'T'HHmmss")}-v1.234.5-pg14.5.sql.gz`,
|
||||||
]);
|
]);
|
||||||
await sut.cleanupDatabaseBackups();
|
await sut.cleanupDatabaseBackups();
|
||||||
expect(mocks.storage.unlink).toHaveBeenCalledTimes(2);
|
expect(mocks.storage.unlink).toHaveBeenCalledTimes(3);
|
||||||
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
||||||
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-1.sql.gz.tmp`,
|
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-1753789649000.sql.gz`,
|
||||||
);
|
);
|
||||||
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
||||||
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-2.sql.gz`,
|
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-20250725T110216-v1.234.5-pg14.5.sql.gz.tmp`,
|
||||||
|
);
|
||||||
|
expect(mocks.storage.unlink).toHaveBeenCalledWith(
|
||||||
|
`${StorageCore.getBaseFolder(StorageFolder.Backups)}/immich-db-backup-20250727T110116-v1.234.5-pg14.5.sql.gz`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -53,9 +53,14 @@ export class BackupService extends BaseService {
|
|||||||
|
|
||||||
const backupsFolder = StorageCore.getBaseFolder(StorageFolder.Backups);
|
const backupsFolder = StorageCore.getBaseFolder(StorageFolder.Backups);
|
||||||
const files = await this.storageRepository.readdir(backupsFolder);
|
const files = await this.storageRepository.readdir(backupsFolder);
|
||||||
const failedBackups = files.filter((file) => file.match(/immich-db-backup-\d+\.sql\.gz\.tmp$/));
|
const failedBackups = files.filter((file) => file.match(/immich-db-backup-.*\.sql\.gz\.tmp$/));
|
||||||
const backups = files
|
const backups = files
|
||||||
.filter((file) => file.match(/immich-db-backup-\d+\.sql\.gz$/))
|
.filter((file) => {
|
||||||
|
const oldBackupStyle = file.match(/immich-db-backup-\d+\.sql\.gz$/);
|
||||||
|
//immich-db-backup-20250729T114018-v1.136.0-pg14.17.sql.gz
|
||||||
|
const newBackupStyle = file.match(/immich-db-backup-\d{8}T\d{6}-v.*-pg.*\.sql\.gz$/);
|
||||||
|
return oldBackupStyle || newBackupStyle;
|
||||||
|
})
|
||||||
.sort()
|
.sort()
|
||||||
.reverse();
|
.reverse();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user