mirror of
https://github.com/whyour/qinglong.git
synced 2026-08-16 22:38:39 +08:00
132 lines
4.3 KiB
JavaScript
132 lines
4.3 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs/promises');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const test = require('node:test');
|
|
const { Op } = require('sequelize');
|
|
|
|
const {
|
|
getDirectorySize,
|
|
normalizeRetentionPolicy,
|
|
} = require('../../back/shared/retention');
|
|
|
|
test('retention policy defaults to disabled and clamps invalid values', () => {
|
|
assert.deepEqual(normalizeRetentionPolicy({}), {
|
|
runningInstanceRetentionDays: 0,
|
|
cronStatRetentionDays: 0,
|
|
});
|
|
assert.deepEqual(
|
|
normalizeRetentionPolicy({
|
|
runningInstanceRetentionDays: -10,
|
|
cronStatRetentionDays: 99999,
|
|
}),
|
|
{
|
|
runningInstanceRetentionDays: 0,
|
|
cronStatRetentionDays: 3650,
|
|
},
|
|
);
|
|
});
|
|
|
|
test('directory preview counts files recursively and ignores symlinks', async (t) => {
|
|
const directory = await fs.mkdtemp(path.join(os.tmpdir(), 'ql-retention-'));
|
|
const nested = path.join(directory, 'nested');
|
|
t.after(() => fs.rm(directory, { recursive: true, force: true }));
|
|
await fs.mkdir(nested);
|
|
await fs.writeFile(path.join(directory, 'one'), Buffer.alloc(7));
|
|
await fs.writeFile(path.join(nested, 'two'), Buffer.alloc(11));
|
|
await fs.symlink(path.join(nested, 'two'), path.join(directory, 'link'));
|
|
|
|
assert.equal(await getDirectorySize(directory), 18);
|
|
assert.equal(await getDirectorySize(path.join(directory, 'missing')), 0);
|
|
});
|
|
|
|
test('cleanup previews first, protects running instances, and uses explicit options', async (t) => {
|
|
const directory = await fs.mkdtemp(path.join(os.tmpdir(), 'ql-retention-'));
|
|
const nodeCache = path.join(directory, 'node');
|
|
await fs.mkdir(nodeCache);
|
|
await fs.writeFile(path.join(nodeCache, 'cache'), Buffer.alloc(13));
|
|
|
|
const config = require('../../back/config').default;
|
|
const originalCachePath = config.dependenceCachePath;
|
|
const RunningInstanceModel = {};
|
|
const CrontabStatModel = {};
|
|
const InstanceStatus = { running: 0 };
|
|
const sequelize = {};
|
|
const stubModule = (modulePath, exports) => {
|
|
require.cache[require.resolve(modulePath)] = {
|
|
id: require.resolve(modulePath),
|
|
filename: require.resolve(modulePath),
|
|
loaded: true,
|
|
exports,
|
|
children: [],
|
|
paths: [],
|
|
};
|
|
};
|
|
stubModule('../../back/data', { sequelize });
|
|
stubModule('../../back/data/cronStats', { CrontabStatModel });
|
|
stubModule('../../back/data/runningInstance', {
|
|
InstanceStatus,
|
|
RunningInstanceModel,
|
|
});
|
|
stubModule('../../back/data/system', {
|
|
AuthDataType: { systemConfig: 'systemConfig' },
|
|
SystemModel: {},
|
|
});
|
|
delete require.cache[require.resolve('../../back/services/retention')];
|
|
const RetentionService = require('../../back/services/retention').default;
|
|
|
|
t.after(async () => {
|
|
config.dependenceCachePath = originalCachePath;
|
|
await fs.rm(directory, { recursive: true, force: true });
|
|
});
|
|
|
|
let instanceWhere;
|
|
let vacuumed = false;
|
|
let instanceCountCalls = 0;
|
|
let statCountCalls = 0;
|
|
config.dependenceCachePath = directory;
|
|
RunningInstanceModel.count = async ({ where }) => {
|
|
instanceCountCalls++;
|
|
instanceWhere = where;
|
|
return 2;
|
|
};
|
|
RunningInstanceModel.destroy = async ({ where }) => {
|
|
instanceWhere = where;
|
|
return 2;
|
|
};
|
|
CrontabStatModel.count = async () => {
|
|
statCountCalls++;
|
|
return 3;
|
|
};
|
|
CrontabStatModel.destroy = async () => 3;
|
|
sequelize.transaction = async (callback) => callback({});
|
|
sequelize.query = async (query) => {
|
|
vacuumed = query === 'VACUUM';
|
|
return [];
|
|
};
|
|
|
|
const service = new RetentionService();
|
|
const disabledPreview = await service.preview({
|
|
runningInstanceRetentionDays: 0,
|
|
cronStatRetentionDays: 0,
|
|
});
|
|
assert.equal(disabledPreview.runningInstances, 0);
|
|
assert.equal(disabledPreview.cronStats, 0);
|
|
assert.equal(instanceCountCalls, 0);
|
|
assert.equal(statCountCalls, 0);
|
|
|
|
const result = await service.cleanup({
|
|
runningInstanceRetentionDays: 30,
|
|
cronStatRetentionDays: 90,
|
|
dependenceCacheTypes: ['node'],
|
|
compactDatabase: true,
|
|
});
|
|
|
|
assert.equal(instanceWhere.status[Op.ne], InstanceStatus.running);
|
|
assert.equal(result.deleted.runningInstances, 2);
|
|
assert.equal(result.deleted.cronStats, 3);
|
|
assert.equal(result.deleted.dependenceCacheBytes, 13);
|
|
assert.equal(vacuumed, true);
|
|
await assert.rejects(fs.stat(nodeCache), { code: 'ENOENT' });
|
|
});
|