mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-11 03:59:09 +00:00
feat(torrent): complete lifecycle controls
This commit is contained in:
@@ -20,7 +20,7 @@ describe('download action policy', () => {
|
||||
expect(canStartDownload(status)).toBe(true);
|
||||
expect(canPauseDownload(status)).toBe(false);
|
||||
}
|
||||
for (const status of ['staged', 'queued', 'downloading', 'seeding', 'processing', 'retrying'] as const) {
|
||||
for (const status of ['staged', 'queued', 'downloading', 'seeding', 'processing', 'verifying', 'retrying'] as const) {
|
||||
expect(canPauseDownload(status)).toBe(true);
|
||||
}
|
||||
for (const status of ['queued', 'downloading', 'processing', 'retrying'] as const) {
|
||||
@@ -40,6 +40,7 @@ describe('download action policy', () => {
|
||||
expect(getPauseResumeAction('queued')).toBe('pause');
|
||||
expect(getPauseResumeAction('downloading')).toBe('pause');
|
||||
expect(getPauseResumeAction('processing')).toBe('pause');
|
||||
expect(getPauseResumeAction('verifying')).toBe('pause');
|
||||
expect(getPauseResumeAction('seeding')).toBe('pause');
|
||||
expect(getPauseResumeAction('retrying')).toBe('pause');
|
||||
expect(getPauseResumeAction('paused')).toBe('resume');
|
||||
|
||||
@@ -15,6 +15,7 @@ const PAUSABLE_STATUSES: ReadonlySet<DownloadStatus> = new Set([
|
||||
'seeding',
|
||||
'waitingToSeed',
|
||||
'processing',
|
||||
'verifying',
|
||||
'retrying',
|
||||
]);
|
||||
|
||||
@@ -66,7 +67,7 @@ export const startActionLabel = (status: DownloadStatus): 'Start' | 'Resume' =>
|
||||
status === 'ready' || status === 'staged' || status === 'failed' ? 'Start' : 'Resume';
|
||||
|
||||
export const isTransferLocked = (status: DownloadStatus): boolean =>
|
||||
status === 'downloading' || status === 'processing' || status === 'seeding' || status === 'waitingToSeed' || status === 'retrying';
|
||||
status === 'downloading' || status === 'processing' || status === 'verifying' || status === 'seeding' || status === 'waitingToSeed' || status === 'retrying';
|
||||
|
||||
export const isIdentityLocked = (status: DownloadStatus): boolean =>
|
||||
isTransferLocked(status) || status === 'completed';
|
||||
|
||||
@@ -73,6 +73,8 @@ export const downloadProgressColorClass = (status: string): string => {
|
||||
return 'download-status-failed';
|
||||
case 'processing':
|
||||
return 'download-status-processing';
|
||||
case 'verifying':
|
||||
return 'download-status-processing';
|
||||
case 'seeding':
|
||||
return 'download-status-seeding';
|
||||
case 'queued':
|
||||
|
||||
@@ -22,6 +22,7 @@ const isFreshDownloadStatus = (status: DownloadItem['status']): boolean =>
|
||||
status === 'downloading' ||
|
||||
status === 'seeding' ||
|
||||
status === 'processing' ||
|
||||
status === 'verifying' ||
|
||||
status === 'retrying';
|
||||
|
||||
const hasPositiveProgress = (download: DownloadItem): boolean =>
|
||||
|
||||
@@ -56,6 +56,14 @@ describe('download persistence progress snapshots', () => {
|
||||
expect(persisted.totalIsEstimate).toBe(false);
|
||||
}
|
||||
);
|
||||
|
||||
it('does not persist verification byte counters across restart', () => {
|
||||
const persisted = redactDownloadForPersistence(item('verifying'));
|
||||
|
||||
expect(persisted.downloadedBytes).toBeUndefined();
|
||||
expect(persisted.totalBytes).toBeUndefined();
|
||||
expect(persisted.totalIsEstimate).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Torrent tracker input validation', () => {
|
||||
|
||||
@@ -30,6 +30,7 @@ const ACTIVE_DOWNLOAD_STATUSES: ReadonlySet<DownloadStatus> = new Set([
|
||||
'queued',
|
||||
'downloading',
|
||||
'processing',
|
||||
'verifying',
|
||||
'seeding',
|
||||
'waitingToSeed',
|
||||
'retrying',
|
||||
@@ -40,7 +41,7 @@ export const isActiveDownloadStatus = (status: DownloadStatus): boolean =>
|
||||
|
||||
/** Transfer states that consume a worker/permit. Queued is intentionally excluded. */
|
||||
export const isTransferActiveStatus = (status: DownloadStatus): boolean =>
|
||||
status === 'downloading' || status === 'processing' || status === 'seeding' || status === 'retrying';
|
||||
status === 'downloading' || status === 'processing' || status === 'verifying' || status === 'seeding' || status === 'retrying';
|
||||
|
||||
export const DOWNLOAD_CONNECTIONS_MIN = 1;
|
||||
export const DOWNLOAD_CONNECTIONS_MAX = 16;
|
||||
@@ -66,6 +67,11 @@ export const normalizeTorrentEncryptionPolicy = (
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export type TorrentFileAllocation = 'prealloc' | 'none';
|
||||
|
||||
export const normalizeTorrentFileAllocation = (value: unknown): TorrentFileAllocation | undefined =>
|
||||
value === 'prealloc' || value === 'none' ? value : undefined;
|
||||
|
||||
export const MAX_TORRENT_TRACKER_TIMEOUT = 604800;
|
||||
export const MAX_TORRENT_TRACKER_INTERVAL = 604800;
|
||||
export const DEFAULT_TORRENT_MAX_OPEN_FILES = 100;
|
||||
@@ -456,6 +462,7 @@ export const isMediaUrl = (rawUrl: string): boolean => {
|
||||
const DOWNLOAD_SECRET_FIELDS = ['password', 'cookies', 'headers'] as const;
|
||||
const VOLATILE_PROGRESS_STATUSES = new Set([
|
||||
'downloading',
|
||||
'verifying',
|
||||
'seeding'
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user