feat: add import preflight summaries

Inspect every manual file, folder, and drag-and-drop import before queue admission. Report exact duplicate, filename-filter, filesystem, destination, configured size-limit, and resulting job counts in the host selection dialog with live bilingual updates.
This commit is contained in:
Sucukdeluxe
2026-08-16 21:31:56 +02:00
parent 16f6f93a72
commit 88a3ee0937
9 changed files with 475 additions and 78 deletions
+104
View File
@@ -0,0 +1,104 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const {
inspectImportEntries,
summarizeImportPlan
} = require('../lib/import-preflight');
describe('import preflight', () => {
it('accounts for candidates, existing and repeated paths, filename filters, unreadable entries and accepted files', async () => {
const sizes = new Map([
['C:\\incoming\\duplicate-new.bin', 2 * 1024 * 1024],
['C:\\incoming\\missing.bin', null],
['C:\\incoming\\unreadable.bin', 'unreadable'],
['C:\\incoming\\empty.bin', 0],
['C:\\incoming\\accepted.xyz', 5 * 1024 * 1024]
]);
const inspection = await inspectImportEntries([
'C:/queue/existing.bin',
'C:/incoming/duplicate-new.bin',
'C:\\incoming\\duplicate-new.bin',
'C:/incoming/skip.sample.bin',
'C:/incoming/missing.bin',
'C:/incoming/unreadable.bin',
'C:/incoming/empty.bin',
'C:/incoming/accepted.xyz'
], {
existingPaths: ['C:\\QUEUE\\existing.bin'],
filenameFilter: {
enabled: true,
action: 'exclude',
conditions: [{ operator: 'contains', value: '.sample.' }]
},
inspectPath: async filePath => {
const value = sizes.get(filePath);
if (value === null) return { exists: false };
if (value === 'unreadable') return { exists: true, readable: false, size: 10 };
return { exists: true, readable: true, size: value };
}
});
assert.equal(inspection.candidateCount, 8);
assert.equal(inspection.duplicateCount, 2);
assert.equal(inspection.filteredCount, 1);
assert.equal(inspection.unavailableCount, 3);
assert.equal(inspection.acceptedCount, 2);
assert.deepEqual(inspection.unavailable.map(entry => entry.reason).sort(), ['empty', 'missing', 'unreadable']);
assert.deepEqual(inspection.accepted.map(entry => entry.name).sort(), ['accepted.xyz', 'duplicate-new.bin']);
assert.equal(inspection.accepted.find(entry => entry.name === 'accepted.xyz').size, 5 * 1024 * 1024);
});
it('counts jobs and only removes jobs blocked by configured host maximum sizes', () => {
const summary = summarizeImportPlan({
inspection: {
candidateCount: 8,
duplicateCount: 2,
filteredCount: 1,
unavailableCount: 3,
accepted: [
{ path: 'C:\\incoming\\small.bin', name: 'small.bin', size: 2 * 1024 * 1024 },
{ path: 'C:\\incoming\\large.custom', name: 'large.custom', size: 5 * 1024 * 1024 }
]
},
selectedHosters: ['unlimited.example', 'limited.example', 'unlimited.example'],
hosterSettings: {
'unlimited.example': { maxSizeMb: 0 },
'limited.example': { maxSizeMb: 3 },
'unknown.example': { maxSizeMb: 1 }
}
});
assert.deepEqual(summary, {
candidateCount: 8,
duplicateCount: 2,
filteredCount: 1,
unavailableCount: 3,
acceptedCount: 2,
targetCount: 2,
jobCount: 3,
sizeLimitedJobCount: 1
});
});
it('limits concurrent file inspections', async () => {
let active = 0;
let maximumActive = 0;
const inspection = await inspectImportEntries(
Array.from({ length: 12 }, (_, index) => `C:/incoming/file-${index}.bin`),
{
concurrency: 3,
inspectPath: async () => {
active++;
maximumActive = Math.max(maximumActive, active);
await new Promise(resolve => setTimeout(resolve, 5));
active--;
return { exists: true, readable: true, size: 1 };
}
}
);
assert.equal(inspection.acceptedCount, 12);
assert.equal(maximumActive, 3);
});
});