diff --git a/migrations/20241209150823-backups-add-archive.js b/migrations/20241209150823-backups-add-archive.js index 15ec2ea2c..16eb10652 100644 --- a/migrations/20241209150823-backups-add-archive.js +++ b/migrations/20241209150823-backups-add-archive.js @@ -1,10 +1,10 @@ 'use strict'; exports.up = async function(db) { - await db.runSql('ALTER TABLE apps ADD COLUMN enableTurn BOOLEAN DEFAULT 1'); + await db.runSql('ALTER TABLE backups ADD COLUMN archive BOOLEAN DEFAULT 0'); }; exports.down = async function(db) { - await db.runSql('ALTER TABLE apps DROP COLUMN enableTurn'); + await db.runSql('ALTER TABLE backups DROP COLUMN archive'); }; diff --git a/src/backupcleaner.js b/src/backupcleaner.js index 2808082b9..83f7dc66b 100644 --- a/src/backupcleaner.js +++ b/src/backupcleaner.js @@ -28,7 +28,9 @@ function applyBackupRetention(allBackups, retention, referencedBackupIds) { const now = new Date(); for (const backup of allBackups) { - if (backup.state === backups.BACKUP_STATE_ERROR) { + if (backup.archive) { + backup.keepReason = 'archive'; + } else if (backup.state === backups.BACKUP_STATE_ERROR) { backup.discardReason = 'error'; } else if (backup.state === backups.BACKUP_STATE_CREATING) { if ((now - backup.creationTime) < 48*60*60*1000) backup.keepReason = 'creating'; diff --git a/src/backups.js b/src/backups.js index ab6468b48..b1666cfd0 100644 --- a/src/backups.js +++ b/src/backups.js @@ -73,7 +73,7 @@ const assert = require('assert'), tasks = require('./tasks.js'), _ = require('underscore'); -const BACKUPS_FIELDS = [ 'id', 'remotePath', 'label', 'identifier', 'creationTime', 'packageVersion', 'type', 'dependsOnJson', 'state', 'manifestJson', 'format', 'preserveSecs', 'encryptionVersion' ]; +const BACKUPS_FIELDS = [ 'id', 'remotePath', 'label', 'identifier', 'creationTime', 'packageVersion', 'type', 'dependsOnJson', 'state', 'manifestJson', 'format', 'preserveSecs', 'encryptionVersion', 'archive' ]; function postProcess(result) { assert.strictEqual(typeof result, 'object'); diff --git a/src/test/backupcleaner-test.js b/src/test/backupcleaner-test.js index 407b359fe..c1639a4ed 100644 --- a/src/test/backupcleaner-test.js +++ b/src/test/backupcleaner-test.js @@ -32,7 +32,8 @@ describe('backup cleaner', function () { dependsOn: [ 'dep1' ], manifest: null, format: 'tgz', - preserveSecs: 0 + preserveSecs: 0, + archive: false }; describe('retention', function () { @@ -43,25 +44,25 @@ describe('backup cleaner', function () { }); it('does not keep latest', function () { - let backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL }; + const backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL }; backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: false }, []); expect(backup.keepReason).to.be(undefined); }); it('always keeps forever policy', function () { - let backup = { creationTime: new Date() }; + const backup = { creationTime: new Date() }; backupCleaner._applyBackupRetention([backup], { keepWithinSecs: -1, keepLatest: true }, []); expect(backup.keepReason).to.be('keepWithinSecs'); }); it('preserveSecs takes precedence', function () { - let backup = { creationTime: new Date(), preserveSecs: 3000 }; + const backup = { creationTime: new Date(), preserveSecs: 3000 }; backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: true }, []); expect(backup.keepReason).to.be('preserveSecs'); }); it('1 daily', function () { - let b = [ + const b = [ { id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, { id: '1', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() }, { id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() }, @@ -78,7 +79,7 @@ describe('backup cleaner', function () { // if you are debugging this test, it's because of some timezone issue with all the hour substraction! it('2 daily, 1 weekly', function () { - let b = [ + const b = [ { id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, { id: '1', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() }, { id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() }, @@ -98,7 +99,7 @@ describe('backup cleaner', function () { }); it('2 daily, 3 monthly, 1 yearly', function () { - let b = [ + const b = [ { id: '0', state: backups.BACKUP_STATE_CREATING, creationTime: moment().toDate() }, { id: '1', state: backups.BACKUP_STATE_ERROR, creationTime: moment().toDate() }, { id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, @@ -122,6 +123,12 @@ describe('backup cleaner', function () { expect(b[8].keepReason).to.be('keepMonthly'); expect(b[9].keepReason).to.be(undefined); }); + + it('keeps archive', function () { + const backup = Object.assign({}, backupTemplate, { archive: true }); + backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 0, keepLatest: false }, []); + expect(backup.keepReason).to.be('archive'); + }); }); describe('task', function () { diff --git a/src/test/backups-test.js b/src/test/backups-test.js index 928195aff..5870a4046 100644 --- a/src/test/backups-test.js +++ b/src/test/backups-test.js @@ -30,7 +30,8 @@ describe('backups', function () { manifest: null, format: 'tgz', preserveSecs: 0, - label: '' + label: '', + archive: false }; const appBackup = { @@ -45,7 +46,8 @@ describe('backups', function () { manifest: { foo: 'bar' }, format: 'tgz', preserveSecs: 0, - label: '' + label: '', + archive: false }; describe('crud', function () {