Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/apps/backups/BackupService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ export class BackupService {
await this.isThereEnoughSpace(filesDiff);
logger.debug({ tag: 'BACKUPS', msg: 'Space check completed' });

const itemsAlreadyBacked = filesDiff.unmodified.length + foldersDiff.unmodified.length;
tracker.addToTotal(filesDiff.total + foldersDiff.total);
const emptyAddedFiles = filesDiff.added.filter((f) => f.size === 0).length;
const itemsAlreadyBacked = filesDiff.unmodified.length + foldersDiff.unmodified.length + emptyAddedFiles;
tracker.incrementProcessed(itemsAlreadyBacked);

logger.debug({ tag: 'BACKUPS', msg: 'Starting folder backup' });
Expand Down Expand Up @@ -212,8 +212,9 @@ export class BackupService {
return;
}
// eslint-disable-next-line no-await-in-loop
await this.fileBatchUploader.run(localRootPath, tree, batch, signal);
tracker.incrementProcessed(batch.length);
await this.fileBatchUploader.run(localRootPath, tree, batch, signal, () => {
tracker.incrementProcessed(1);
});
}
}

Expand All @@ -227,13 +228,13 @@ export class BackupService {
const batches = ModifiedFilesBatchCreator.run(modified);

for (const batch of batches) {
logger.debug({ tag: 'BACKUPS', msg: 'Signal aborted', aborted: signal.aborted });
if (signal.aborted) {
return;
}
// eslint-disable-next-line no-await-in-loop
await this.fileBatchUpdater.run(localTree.root, remoteTree, Array.from(batch.keys()), signal);
tracker.incrementProcessed(batch.size);
await this.fileBatchUpdater.run(localTree.root, remoteTree, Array.from(batch.keys()), signal, () => {
tracker.incrementProcessed(1);
});
}
}

Expand All @@ -249,7 +250,7 @@ export class BackupService {

// eslint-disable-next-line no-await-in-loop
await addFileToTrash(file.uuid);
tracker.incrementProcessed(1);
}
tracker.incrementProcessed(deleted.length);
}
}
91 changes: 91 additions & 0 deletions src/backend/features/backup/backup-progress-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
export type BackupProgressState = {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file lacks tests

readonly processedItems: number;
readonly backupWeights: ReadonlyMap<string, number>;
readonly backupTotals: ReadonlyMap<string, number>;
readonly currentBackupId: string;
readonly completedBackups: ReadonlySet<string>;
};

export const createInitialState = (): BackupProgressState => ({

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for better structure, its better to use function rather than arrow function unless its necessary

processedItems: 0,
backupWeights: new Map(),
backupTotals: new Map(),
currentBackupId: '',
completedBackups: new Set(),
});

export const initializeWeights = (
state: BackupProgressState,
backupIds: string[],
fileCounts: ReadonlyMap<string, number>,
): BackupProgressState => {
const totalFiles = Array.from(fileCounts.values()).reduce((a, b) => a + b, 0);

if (totalFiles === 0) {
return state;
}

const weights = new Map<string, number>();
const totals = new Map<string, number>();

backupIds.forEach((id) => {
const count = fileCounts.get(id) || 1;
weights.set(id, count / totalFiles);
totals.set(id, count);
});

return {
...state,
backupWeights: weights,
backupTotals: totals,
};
};

export const setCurrentBackupId = (state: BackupProgressState, backupId: string): BackupProgressState => ({
...state,
currentBackupId: backupId,
processedItems: 0,
});

export const incrementProcessed = (state: BackupProgressState, count: number = 1): BackupProgressState => ({
...state,
processedItems: state.processedItems + count,
});

export const markBackupAsCompleted = (state: BackupProgressState, backupId: string): BackupProgressState => ({
...state,
completedBackups: new Set([...state.completedBackups, backupId]),
});

export const getPercentage = (state: BackupProgressState): number => {
let weightedProgress = 0;

for (const backupId of state.completedBackups) {
const weight = state.backupWeights.get(backupId) || 0;
weightedProgress += weight * 100;
}

if (state.backupWeights.has(state.currentBackupId) && !state.completedBackups.has(state.currentBackupId)) {
const currentWeight = state.backupWeights.get(state.currentBackupId)!;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

careful with this

const currentTotal = state.backupTotals.get(state.currentBackupId) || 1;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be always <=1 right?


if (currentTotal > 0) {
const backupProgress = (state.processedItems / currentTotal) * 100;
weightedProgress += currentWeight * backupProgress;
}
}

return Math.min(100, Math.round(weightedProgress));
};

export const resetState = (): BackupProgressState => createInitialState();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is not really neessary then


export const initializeAndSetBackup = (
state: BackupProgressState,
backupIds: string[],
fileCounts: ReadonlyMap<string, number>,
firstBackupId: string,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be the first item of the array, right?

): BackupProgressState => {
const weightedState = initializeWeights(state, backupIds, fileCounts);
return setCurrentBackupId(weightedState, firstBackupId);
};
Loading
Loading