Restore the v2.1.19 application baseline and retain only the focused import preflight summary with duplicate, unavailable, destination, job, and size-limit visibility.
This commit is contained in:
@@ -48,13 +48,13 @@ test('prepareGroups creates one Windows manifest with a stable token and immutab
|
||||
token: 'cleanup-1',
|
||||
file: 'C:\\Uploads\\Movie.MKV',
|
||||
requiredHosters: ['doodstream.com', 'voe.sx', 'vidmoly.me', 'byse.sx'],
|
||||
confirmedHosters: [],
|
||||
completedHosters: ['doodstream.com', 'voe.sx'],
|
||||
fingerprint: null,
|
||||
jobs: [
|
||||
{ jobId: 'job-doodstream', hoster: 'doodstream.com', status: 'done', currentRound: false },
|
||||
{ jobId: 'job-voe', hoster: 'voe.sx', status: 'done', currentRound: false },
|
||||
{ jobId: 'job-vidmoly', hoster: 'vidmoly.me', status: 'error', currentRound: true },
|
||||
{ jobId: 'job-byse', hoster: 'byse.sx', status: 'preview', currentRound: false }
|
||||
{ jobId: 'job-doodstream', hoster: 'doodstream.com', status: 'done' },
|
||||
{ jobId: 'job-voe', hoster: 'voe.sx', status: 'done' },
|
||||
{ jobId: 'job-vidmoly', hoster: 'vidmoly.me', status: 'error' },
|
||||
{ jobId: 'job-byse', hoster: 'byse.sx', status: 'preview' }
|
||||
]
|
||||
});
|
||||
assert.deepEqual(queueJobs.map((job) => job.sourceCleanupToken), [
|
||||
@@ -74,13 +74,11 @@ test('prepareGroups creates one Windows manifest with a stable token and immutab
|
||||
assert.doesNotThrow(() => JSON.stringify(prepared.groups));
|
||||
});
|
||||
|
||||
test('prepareGroups reuses confirmed metadata across a partial retry', () => {
|
||||
test('prepareGroups reuses persisted metadata across a partial retry', () => {
|
||||
const queueJobs = queueFixture();
|
||||
policy.prepareGroups(queueJobs, queueJobs, () => 'cleanup-1', 'win32');
|
||||
for (const job of queueJobs) {
|
||||
job.sourceCleanupMetadataVersion = 2;
|
||||
job.sourceCleanupConfirmedHosters = ['doodstream.com', 'voe.sx'];
|
||||
}
|
||||
queueJobs[0].sourceCleanupCompletedHosters = ['doodstream.com', 'voe.sx'];
|
||||
queueJobs[1].sourceCleanupCompletedHosters = ['doodstream.com', 'voe.sx'];
|
||||
queueJobs[0].status = 'preview';
|
||||
queueJobs[1].status = 'preview';
|
||||
|
||||
@@ -95,7 +93,7 @@ test('prepareGroups reuses confirmed metadata across a partial retry', () => {
|
||||
'vidmoly.me',
|
||||
'byse.sx'
|
||||
]);
|
||||
assert.deepEqual(prepared.groups[0].confirmedHosters, ['doodstream.com', 'voe.sx']);
|
||||
assert.deepEqual(prepared.groups[0].completedHosters, ['doodstream.com', 'voe.sx']);
|
||||
assert.equal(prepared.groups[0].jobs.find((job) => job.hoster === 'vidmoly.me').status, 'error');
|
||||
});
|
||||
|
||||
@@ -151,7 +149,7 @@ test('removing a failed job never relaxes the stored requirements', () => {
|
||||
|
||||
test('removeRequirement drops only an explicitly discarded unstarted hoster', () => {
|
||||
const queueJobs = queueFixture();
|
||||
policy.prepareGroups(queueJobs, queueJobs.slice(0, 3), () => 'cleanup-1', 'win32');
|
||||
policy.prepareGroups(queueJobs, queueJobs, () => 'cleanup-1', 'win32');
|
||||
|
||||
const touchedJobs = policy.removeRequirement(queueJobs, queueJobs[3], 'win32');
|
||||
|
||||
@@ -165,7 +163,7 @@ test('removeRequirement drops only an explicitly discarded unstarted hoster', ()
|
||||
}
|
||||
});
|
||||
|
||||
test('markCompleted keeps successful hosters provisional for the current round', () => {
|
||||
test('markCompleted preserves successful hosters for later retries', () => {
|
||||
const queueJobs = queueFixture();
|
||||
policy.prepareGroups(queueJobs, queueJobs, () => 'cleanup-1', 'win32');
|
||||
|
||||
@@ -173,108 +171,10 @@ test('markCompleted keeps successful hosters provisional for the current round',
|
||||
policy.markCompleted(queueJobs, queueJobs[2], 'win32');
|
||||
|
||||
for (const job of queueJobs) {
|
||||
assert.deepEqual(job.sourceCleanupConfirmedHosters, []);
|
||||
assert.deepEqual(job.sourceCleanupProvisionalHosters, ['vidmoly.me']);
|
||||
}
|
||||
});
|
||||
|
||||
test('a started cleanup requirement survives abort finalization persistence and restart', async () => {
|
||||
const queueJobs = [
|
||||
{ id: 'job-complete', file: 'C:\\Uploads\\Protected.mkv', hoster: 'doodstream.com', status: 'preview' },
|
||||
{ id: 'job-started', file: 'C:\\Uploads\\Protected.mkv', hoster: 'voe.sx', status: 'preview' }
|
||||
];
|
||||
policy.prepareGroups(queueJobs, queueJobs, () => 'cleanup-protected', 'win32');
|
||||
queueJobs[0].status = 'done';
|
||||
policy.markCompleted(queueJobs, queueJobs[0], 'win32');
|
||||
queueJobs[1].status = 'aborted';
|
||||
await policy.persistRoundCompletions(queueJobs, { historyPersisted: true, persist: async () => true });
|
||||
|
||||
const restored = structuredClone(queueJobs);
|
||||
restored[1].status = 'preview';
|
||||
restored[1].interrupted = false;
|
||||
const touchedJobs = policy.removeRequirement(restored, restored[1], 'win32');
|
||||
|
||||
assert.deepEqual(touchedJobs, []);
|
||||
assert.deepEqual(restored.map(job => job.sourceCleanupStartedHosters), [
|
||||
['doodstream.com', 'voe.sx'],
|
||||
['doodstream.com', 'voe.sx']
|
||||
]);
|
||||
assert.deepEqual(restored.map(job => job.sourceCleanupRequiredHosters), [
|
||||
['doodstream.com', 'voe.sx'],
|
||||
['doodstream.com', 'voe.sx']
|
||||
]);
|
||||
});
|
||||
|
||||
test('legacy version two cleanup metadata without started hosters fails closed', () => {
|
||||
const queueJobs = [
|
||||
{
|
||||
id: 'legacy-complete',
|
||||
file: 'C:\\Uploads\\Legacy.mkv',
|
||||
hoster: 'doodstream.com',
|
||||
status: 'done',
|
||||
sourceCleanupMetadataVersion: 2,
|
||||
sourceCleanupToken: 'cleanup-legacy',
|
||||
sourceCleanupRequiredHosters: ['doodstream.com', 'voe.sx'],
|
||||
sourceCleanupConfirmedHosters: ['doodstream.com']
|
||||
},
|
||||
{
|
||||
id: 'legacy-candidate',
|
||||
file: 'C:\\Uploads\\Legacy.mkv',
|
||||
hoster: 'voe.sx',
|
||||
status: 'preview',
|
||||
sourceCleanupMetadataVersion: 2,
|
||||
sourceCleanupToken: 'cleanup-legacy',
|
||||
sourceCleanupRequiredHosters: ['doodstream.com', 'voe.sx'],
|
||||
sourceCleanupConfirmedHosters: ['doodstream.com']
|
||||
}
|
||||
];
|
||||
|
||||
const touchedJobs = policy.removeRequirement(queueJobs, queueJobs[1], 'win32');
|
||||
|
||||
assert.deepEqual(touchedJobs, []);
|
||||
assert.deepEqual(queueJobs.map(job => job.sourceCleanupRequiredHosters), [
|
||||
['doodstream.com', 'voe.sx'],
|
||||
['doodstream.com', 'voe.sx']
|
||||
]);
|
||||
});
|
||||
|
||||
test('removeRequirement never relaxes requirements for started or interrupted jobs', () => {
|
||||
for (const candidate of [
|
||||
{ status: 'queued' },
|
||||
{ status: 'getting-server' },
|
||||
{ status: 'uploading' },
|
||||
{ status: 'retrying' },
|
||||
{ status: 'preview', interrupted: true }
|
||||
]) {
|
||||
const queueJobs = [
|
||||
{
|
||||
id: 'job-complete',
|
||||
file: 'C:\\Uploads\\Protected.mkv',
|
||||
hoster: 'doodstream.com',
|
||||
status: 'done',
|
||||
sourceCleanupMetadataVersion: 2,
|
||||
sourceCleanupToken: 'cleanup-protected',
|
||||
sourceCleanupRequiredHosters: ['doodstream.com', 'voe.sx'],
|
||||
sourceCleanupConfirmedHosters: ['doodstream.com']
|
||||
},
|
||||
{
|
||||
id: 'job-candidate',
|
||||
file: 'C:\\Uploads\\Protected.mkv',
|
||||
hoster: 'voe.sx',
|
||||
sourceCleanupMetadataVersion: 2,
|
||||
sourceCleanupToken: 'cleanup-protected',
|
||||
sourceCleanupRequiredHosters: ['doodstream.com', 'voe.sx'],
|
||||
sourceCleanupConfirmedHosters: ['doodstream.com'],
|
||||
...candidate
|
||||
}
|
||||
];
|
||||
|
||||
const touchedJobs = policy.removeRequirement(queueJobs, queueJobs[1], 'win32');
|
||||
|
||||
assert.deepEqual(touchedJobs, []);
|
||||
assert.deepEqual(queueJobs.map(job => job.sourceCleanupRequiredHosters), [
|
||||
['doodstream.com', 'voe.sx'],
|
||||
['doodstream.com', 'voe.sx']
|
||||
assert.deepEqual(job.sourceCleanupCompletedHosters, [
|
||||
'doodstream.com',
|
||||
'voe.sx',
|
||||
'vidmoly.me'
|
||||
]);
|
||||
}
|
||||
});
|
||||
@@ -303,127 +203,3 @@ test('applyFingerprints attaches Main fingerprints by token and includes them in
|
||||
assert.notEqual(job.sourceCleanupFingerprint, fingerprint);
|
||||
}
|
||||
});
|
||||
|
||||
test('keeps round successes provisional until history and queue persistence succeed', async () => {
|
||||
const queueJobs = [
|
||||
{ id: 'job-voe', file: 'C:\\Uploads\\Round.bin', hoster: 'voe.sx', status: 'preview' },
|
||||
{ id: 'job-byse', file: 'C:\\Uploads\\Round.bin', hoster: 'byse.sx', status: 'error' }
|
||||
];
|
||||
policy.prepareGroups(queueJobs, queueJobs, () => 'cleanup-round', 'win32');
|
||||
queueJobs[0].status = 'done';
|
||||
|
||||
policy.markCompleted(queueJobs, queueJobs[0], 'win32');
|
||||
|
||||
for (const job of queueJobs) {
|
||||
assert.deepEqual(job.sourceCleanupConfirmedHosters, []);
|
||||
assert.deepEqual(job.sourceCleanupProvisionalHosters, ['voe.sx']);
|
||||
}
|
||||
|
||||
let persistedHosters = null;
|
||||
const queuePersisted = await policy.persistRoundCompletions(queueJobs, {
|
||||
historyPersisted: true,
|
||||
persist: async () => {
|
||||
persistedHosters = queueJobs.map((job) => [...job.sourceCleanupConfirmedHosters]);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(queuePersisted, true);
|
||||
assert.deepEqual(persistedHosters, [['voe.sx'], ['voe.sx']]);
|
||||
for (const job of queueJobs) {
|
||||
assert.deepEqual(job.sourceCleanupConfirmedHosters, ['voe.sx']);
|
||||
assert.deepEqual(job.sourceCleanupProvisionalHosters, []);
|
||||
}
|
||||
});
|
||||
|
||||
test('rolls back provisional promotion when the final queue save fails', async () => {
|
||||
const queueJobs = [
|
||||
{
|
||||
id: 'job-voe',
|
||||
file: 'C:\\Uploads\\Partial.bin',
|
||||
hoster: 'voe.sx',
|
||||
status: 'done',
|
||||
sourceCleanupMetadataVersion: 2,
|
||||
sourceCleanupToken: 'cleanup-partial',
|
||||
sourceCleanupRequiredHosters: ['voe.sx', 'byse.sx'],
|
||||
sourceCleanupConfirmedHosters: ['voe.sx']
|
||||
},
|
||||
{
|
||||
id: 'job-byse',
|
||||
file: 'C:\\Uploads\\Partial.bin',
|
||||
hoster: 'byse.sx',
|
||||
status: 'preview',
|
||||
sourceCleanupMetadataVersion: 2,
|
||||
sourceCleanupToken: 'cleanup-partial',
|
||||
sourceCleanupRequiredHosters: ['voe.sx', 'byse.sx'],
|
||||
sourceCleanupConfirmedHosters: ['voe.sx']
|
||||
}
|
||||
];
|
||||
policy.prepareGroups(queueJobs, [queueJobs[1]], () => 'unused', 'win32');
|
||||
queueJobs[1].status = 'done';
|
||||
policy.markCompleted(queueJobs, queueJobs[1], 'win32');
|
||||
|
||||
const queuePersisted = await policy.persistRoundCompletions(queueJobs, {
|
||||
historyPersisted: true,
|
||||
persist: async () => false
|
||||
});
|
||||
|
||||
assert.equal(queuePersisted, false);
|
||||
for (const job of queueJobs) {
|
||||
assert.deepEqual(job.sourceCleanupConfirmedHosters, ['voe.sx']);
|
||||
assert.deepEqual(job.sourceCleanupProvisionalHosters, []);
|
||||
}
|
||||
});
|
||||
|
||||
test('ignores legacy v2.1.19 completed markers when preparing a retry', () => {
|
||||
const queueJobs = [{
|
||||
id: 'job-voe',
|
||||
file: 'C:\\Uploads\\Legacy.bin',
|
||||
hoster: 'voe.sx',
|
||||
status: 'error',
|
||||
sourceCleanupToken: 'cleanup-legacy',
|
||||
sourceCleanupRequiredHosters: ['voe.sx'],
|
||||
sourceCleanupCompletedHosters: ['voe.sx']
|
||||
}];
|
||||
|
||||
const prepared = policy.prepareGroups(queueJobs, queueJobs, () => 'unused', 'win32');
|
||||
|
||||
assert.deepEqual(prepared.groups[0].confirmedHosters, []);
|
||||
assert.equal(queueJobs[0].sourceCleanupMetadataVersion, 2);
|
||||
assert.deepEqual(queueJobs[0].sourceCleanupConfirmedHosters, []);
|
||||
assert.equal(Object.prototype.hasOwnProperty.call(queueJobs[0], 'sourceCleanupCompletedHosters'), false);
|
||||
});
|
||||
|
||||
test('selecting a confirmed hoster for retry revokes its durable completion', () => {
|
||||
const queueJobs = [
|
||||
{
|
||||
id: 'job-voe',
|
||||
file: 'C:\\Uploads\\Retry.bin',
|
||||
hoster: 'voe.sx',
|
||||
status: 'preview',
|
||||
sourceCleanupMetadataVersion: 2,
|
||||
sourceCleanupToken: 'cleanup-retry',
|
||||
sourceCleanupRequiredHosters: ['voe.sx', 'byse.sx'],
|
||||
sourceCleanupConfirmedHosters: ['voe.sx', 'byse.sx']
|
||||
},
|
||||
{
|
||||
id: 'job-byse',
|
||||
file: 'C:\\Uploads\\Retry.bin',
|
||||
hoster: 'byse.sx',
|
||||
status: 'done',
|
||||
sourceCleanupMetadataVersion: 2,
|
||||
sourceCleanupToken: 'cleanup-retry',
|
||||
sourceCleanupRequiredHosters: ['voe.sx', 'byse.sx'],
|
||||
sourceCleanupConfirmedHosters: ['voe.sx', 'byse.sx']
|
||||
}
|
||||
];
|
||||
|
||||
const prepared = policy.prepareGroups(queueJobs, [queueJobs[0]], () => 'unused', 'win32');
|
||||
|
||||
assert.deepEqual(prepared.groups[0].confirmedHosters, ['byse.sx']);
|
||||
assert.equal(prepared.groups[0].jobs[0].currentRound, true);
|
||||
assert.equal(prepared.groups[0].jobs[1].currentRound, false);
|
||||
for (const job of queueJobs) {
|
||||
assert.deepEqual(job.sourceCleanupConfirmedHosters, ['byse.sx']);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user