Skip to content

Commit

Permalink
Completed the task of implementing manual backup for one or more folders
Browse files Browse the repository at this point in the history
  • Loading branch information
ArceDanielShok committed Oct 3, 2024
2 parents a18c669 + f578d2a commit cc0ae1c
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 75 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "internxt-drive",
"version": "2.1.3",
"version": "2.2.0",
"author": "Internxt <[email protected]>",
"description": "Internxt Drive client UI",
"license": "AGPL-3.0",
Expand Down
2 changes: 1 addition & 1 deletion release/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "internxt-drive",
"version": "2.1.3",
"version": "2.2.0",
"description": "Internxt Drive client UI",
"main": "./dist/main/main.js",
"author": "Internxt <[email protected]>",
Expand Down
159 changes: 88 additions & 71 deletions src/apps/backups/Backups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import {
FoldersDiff,
FoldersDiffCalculator,
} from './diff/FoldersDiffCalculator';
import { getParentDirectory, relative, relativeV2 } from './utils/relative';
import { getParentDirectory, relativeV2 } from './utils/relative';
import { DriveDesktopError } from '../../context/shared/domain/errors/DriveDesktopError';
import { UserAvaliableSpaceValidator } from '../../context/user/usage/application/UserAvaliableSpaceValidator';
import { FileDeleter } from '../../context/virtual-drive/files/application/delete/FileDeleter';
import { RemoteTreeBuilder } from '../../context/virtual-drive/remoteTree/application/RemoteTreeBuilder';
import { RemoteTree } from '../../context/virtual-drive/remoteTree/domain/RemoteTree';
import { FolderDeleter } from '../../context/virtual-drive/folders/application/delete/FolderDeleter';
import { LocalFolder } from '../../context/local/localFolder/domain/LocalFolder';

@Service()
export class Backup {
Expand All @@ -33,7 +35,7 @@ export class Backup {
private readonly fileBatchUploader: FileBatchUploader,
private readonly fileBatchUpdater: FileBatchUpdater,
private readonly remoteFileDeleter: FileDeleter,
// private readonly remoteFolderDeleter: FileDeleter,
private readonly remoteFolderDeleter: FolderDeleter,
private readonly simpleFolderCreator: SimpleFolderCreator,
private readonly userAvaliableSpaceValidator: UserAvaliableSpaceValidator
) {}
Expand All @@ -46,37 +48,23 @@ export class Backup {
): Promise<DriveDesktopError | undefined> {
Logger.info('[BACKUPS] Backing:', info);

Logger.info('[BACKUPS] Generating local tree');
const localTreeEither = await this.localTreeBuilder.run(
info.pathname as AbsolutePath
);

Logger.debug('[BACKUPS] Local tree either', localTreeEither);

if (localTreeEither.isLeft()) {
Logger.error('[BACKUPS] local tree is left', localTreeEither);
return localTreeEither.getLeft();
}

const local = localTreeEither.getRight();

Logger.info('[BACKUPS] Generating remote tree', info.folderId);
const remote = await this.remoteTreeBuilder.run(info.folderId, true);

Logger.debug('[BACKUPS] Remote tree', JSON.stringify(remote));

Logger.debug('[BACKUPS] Remote tree file', remote.files);

Logger.debug('[BACKUPS] Remote tree folder', remote.folders);

const foldersDiff = FoldersDiffCalculator.calculate(local, remote);

Logger.debug('[BACKUPS] Folders diff', foldersDiff);

const filesDiff = DiffFilesCalculator.calculate(local, remote);

Logger.debug('[BACKUPS] Files diff', filesDiff);

await this.isThereEnoughSpace(filesDiff);

const alreadyBacked =
Expand All @@ -90,7 +78,7 @@ export class Backup {
alreadyBacked
);

await this.backupFolders(foldersDiff, local, remote);
await this.backupFolders(foldersDiff, local, remote, abortController);

await this.backupFiles(filesDiff, local, remote, abortController);

Expand Down Expand Up @@ -130,49 +118,27 @@ export class Backup {
private async backupFolders(
diff: FoldersDiff,
local: LocalTree,
remote: RemoteTree
remote: RemoteTree,
abortController: AbortController
) {
Logger.info('[BACKUPS] Backing folders');
Logger.info('[BACKUPS] Folders added', diff.added.length);

// const { added, modified, deleted } = diff;

await Promise.all(
diff.added.map(async (localFolder) => {
const relativePath = relativeV2(local.root.path, localFolder.path);

if (relativePath === '/') {
return; // Ignorar la carpeta raíz
}

const remoteParentPath = getParentDirectory(
local.root.path,
localFolder.path
);
const parentExists = remote.has(remoteParentPath);

if (!parentExists) {
return;
}

const parent = remote.getParent(remoteParentPath);
const existingItems = remote.has(relativePath);
const { added, deleted } = diff;

if (existingItems) {
return;
}

const folder = await this.simpleFolderCreator.run(
relativePath,
parent.id
);

remote.addFolder(parent, folder);
const deleteFolder = await this.deleteRemoteFolders(
deleted,
abortController
);

this.backed++;
BackupsIPCRenderer.send('backups.progress-update', this.backed);
})
Logger.debug('[BACKUPS] start upload', deleted.length);
const uploadFolder = await this.uploadAndCreateFolder(
local.root.path,
added,
remote
);

return await Promise.all([deleteFolder, uploadFolder]);
}

private async backupFiles(
Expand All @@ -186,7 +152,12 @@ export class Backup {
const { added, modified, deleted } = filesDiff;

Logger.info('[BACKUPS] Files added', added.length);
await this.uploadAndCreate(local.root.path, added, remote, abortController);
await this.uploadAndCreateFile(
local.root.path,
added,
remote,
abortController
);

Logger.info('[BACKUPS] Files modified', modified.size);
await this.uploadAndUpdate(modified, local, remote, abortController);
Expand All @@ -195,7 +166,7 @@ export class Backup {
await this.deleteRemoteFiles(deleted, abortController);
}

private async uploadAndCreate(
private async uploadAndCreateFile(
localRootPath: string,
added: Array<LocalFile>,
tree: RemoteTree,
Expand Down Expand Up @@ -265,20 +236,66 @@ export class Backup {
BackupsIPCRenderer.send('backups.progress-update', this.backed);
}

// private async deleteRemoteFolders(
// deleted: Array<Folder>,
// abortController: AbortController
// ) {
// for (const folder of deleted) {
// if (abortController.signal.aborted) {
// return;
// }

// // eslint-disable-next-line no-await-in-loop
// await this.remoteFileDeleter.run(folder);
// }

// this.backed += deleted.length;
// BackupsIPCRenderer.send('backups.progress-update', this.backed);
// }
private async deleteRemoteFolders(
deleted: Array<Folder>,
abortController: AbortController
) {
for (const folder of deleted) {
if (abortController.signal.aborted) {
return;
}

// eslint-disable-next-line no-await-in-loop
await this.remoteFolderDeleter.run(folder);
}

this.backed += deleted.length;
BackupsIPCRenderer.send('backups.progress-update', this.backed);
}

private async uploadAndCreateFolder(
localRootPath: string,
added: Array<LocalFolder>,
tree: RemoteTree
): Promise<void> {
for (const localFolder of added) {
const relativePath = relativeV2(localRootPath, localFolder.path);

Logger.debug('[BACKUPS] Relative path of folder', relativePath);

if (relativePath === '/') {
Logger.debug('[BACKUPS] Ignoring root folder');
continue; // Ignorar la carpeta raíz
}

const remoteParentPath = getParentDirectory(
localRootPath,
localFolder.path
);
const parentExists = tree.has(remoteParentPath);

if (!parentExists) {
Logger.debug('[BACKUPS] Parent folder does not exist');
continue;
}

const parent = tree.getParent(remoteParentPath);
const existingItems = tree.has(relativePath);

if (existingItems) {
Logger.debug('[BACKUPS] Folder already exists');
continue;
}

const folder = await this.simpleFolderCreator.run(
relativePath,
parent.id
);

tree.addFolder(parent, folder);

this.backed++;
BackupsIPCRenderer.send('backups.progress-update', this.backed);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SimpleFolderCreator } from '../../../../context/virtual-drive/folders/a
import { AuthorizedClients } from '../../../shared/HttpClient/Clients';
import { HttpRemoteFolderSystem } from '../../../../context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem';
import { RemoteFolderSystem } from '../../../../context/virtual-drive/folders/domain/file-systems/RemoteFolderSystem';
import { FolderDeleter } from '../../../../context/virtual-drive/folders/application/delete/FolderDeleter';

export async function registerFolderServices(builder: ContainerBuilder) {
builder
Expand All @@ -18,4 +19,5 @@ export async function registerFolderServices(builder: ContainerBuilder) {
.private();

builder.registerAndUse(SimpleFolderCreator);
builder.registerAndUse(FolderDeleter);
}
2 changes: 1 addition & 1 deletion src/apps/main/background-processes/backups/BackupsIpc.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ipcMain } from 'electron';
import { TypedIPC } from '../../../shared/IPC/TypedIPC';
import { BackgroundProcessBackupsMessages } from '../../../shared/IPC/events/backups/BackgroundProcessBackupsMessages';
import { MainProcessBackupsMessages } from '../../../shared/IPC/events/backups/MainProcessBackupsMessages';
import { MainProcessBackupsMessages } from '../../../shared/IPC/events/backups/MainProcessBuckupsMessages';

type BackupsIPCMain = TypedIPC<
BackgroundProcessBackupsMessages,
Expand Down
1 change: 0 additions & 1 deletion src/apps/renderer/hooks/useUsage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export default function useUsage() {
setUsage(usage);
setStatus('ready');
} catch (err) {
console.error(err);
setStatus('error');
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Service } from 'diod';
import { Folder } from '../../domain/Folder';
import { RemoteFolderSystem } from '../../domain/file-systems/RemoteFolderSystem';

@Service()
export class FolderDeleter {
constructor(private readonly fs: RemoteFolderSystem) {}

async run(folder: Folder) {
await this.fs.trash(folder.id);
}
}

0 comments on commit cc0ae1c

Please sign in to comment.