From cd045a8769899f2c93881546d938c6815c2776f1 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 31 Jul 2024 21:01:58 -0300 Subject: [PATCH 01/18] Refactor: Removed unused function --- src/apps/shared/HttpClient/HttpClient.ts | 2 +- src/context/virtual-drive/files/application/FileCreator.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/apps/shared/HttpClient/HttpClient.ts b/src/apps/shared/HttpClient/HttpClient.ts index 75150cfbe..a422e9310 100644 --- a/src/apps/shared/HttpClient/HttpClient.ts +++ b/src/apps/shared/HttpClient/HttpClient.ts @@ -15,7 +15,7 @@ export class AuthorizedHttpClient { private handleUnauthorizedResponse(error: AxiosError) { if (error?.response?.status === 401) { Logger.warn('[AUTH] Request unauthorized'); - this.unauthorizedNotifier(); + // this.unauthorizedNotifier(); } // Prevent the token from being displayed in the logs diff --git a/src/context/virtual-drive/files/application/FileCreator.ts b/src/context/virtual-drive/files/application/FileCreator.ts index 341d5693d..739cb99d9 100644 --- a/src/context/virtual-drive/files/application/FileCreator.ts +++ b/src/context/virtual-drive/files/application/FileCreator.ts @@ -51,10 +51,6 @@ export class FileCreator { Logger.debug('[DEBUG IN FILECREATOR STEEP 3]' + filePath.value); - const existingPersistedFile = await this.remote.checkStatusFile(contents.id); - - Logger.debug('[DEBUG IN FILECREATOR STEEP 3.1]' + existingPersistedFile); - const persistedAttributes = await this.remote.persist(offline); Logger.debug('[DEBUG IN FILECREATOR STEEP 4]' + filePath.value); From 6d921fa4ae1ab321164fc6eadc75d5f374f214cf Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 21 Aug 2024 16:45:36 -0300 Subject: [PATCH 02/18] Fixed issue with updating folders as described in ticket PB-2665 --- src/apps/main/realtime.ts | 3 -- src/apps/sync-engine/BindingManager.ts | 39 +++++++++++-------- .../folders/application/FolderPathUpdater.ts | 8 +--- .../virtual-drive/folders/domain/Folder.ts | 3 -- .../folders/domain/OfflineFolder.ts | 3 -- 5 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/apps/main/realtime.ts b/src/apps/main/realtime.ts index 756b2a231..f14774ac8 100644 --- a/src/apps/main/realtime.ts +++ b/src/apps/main/realtime.ts @@ -3,7 +3,6 @@ import { io, Socket } from 'socket.io-client'; import { obtainToken } from './auth/service'; import eventBus from './event-bus'; import { broadcastToWindows } from './windows'; -import * as Sentry from '@sentry/electron/main'; type XHRRequest = { getResponseHeader: (headerName: string) => string[] | null; @@ -54,12 +53,10 @@ function cleanAndStartRemoteNotifications() { socket.on('disconnect', (reason) => { logger.log('❌ Remote notifications disconnected, reason: ', reason); - Sentry.captureException(reason); }); socket.on('connect_error', (error) => { logger.error('❌ Remote notifications connect error: ', error); - Sentry.captureException(error); }); socket.on('event', (data) => { diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index 0e79ac04a..1692ad6b0 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -18,6 +18,7 @@ import * as Sentry from '@sentry/electron/renderer'; import { runner } from '../utils/runner'; import { QueueManager } from './dependency-injection/common/QueueManager'; import { DependencyInjectionLogWatcherPath } from './dependency-injection/common/logEnginePath'; +import configStore from '../main/config'; export type CallbackDownload = ( success: boolean, @@ -34,6 +35,8 @@ export class BindingsManager { private progressBuffer = 0; private controllers: IControllers; + private lastHydrated = ''; + constructor( private readonly container: DependencyContainer, private readonly paths: { @@ -110,13 +113,7 @@ export class BindingsManager { ), }); fn(absolutePath, contentsId, callback); - const isFolder = fs.lstatSync(absolutePath).isDirectory(); - - this.container.virtualDrive.updateSyncStatus( - absolutePath, - isFolder, - true - ); + Logger.debug('Finish Rename', absolutePath); } catch (error) { Logger.error('Error during rename or move operation', error); } @@ -151,6 +148,9 @@ export class BindingsManager { .split(':')[1] ); Logger.debug('[Fetch Data Callback] Preparing begins', path); + Logger.debug('[Fetch Data Callback] Preparing begins', file.path); + this.lastHydrated = file.path; + let finished = false; try { while (!finished) { @@ -301,19 +301,26 @@ export class BindingsManager { }, handleHydrate: async (task: QueueItem) => { try { + const syncRoot = configStore.get('syncRoot'); Logger.debug('[Handle Hydrate Callback] Preparing begins', task.path); + const normalizePath = (path: string) => path.replace(/\\/g, '/'); - const atributtes = - await this.container.virtualDrive.getPlaceholderAttribute( - task.path - ); - Logger.debug('atributtes', atributtes); - - const status = await this.container.virtualDrive.getPlaceholderState( - task.path + const normalizedLastHydrated = normalizePath(this.lastHydrated); + let normalizedTaskPath = normalizePath( + task.path.replace(syncRoot, '') ); - Logger.debug('status', status); + if (!normalizedTaskPath.startsWith('/')) { + normalizedTaskPath = '/' + normalizedTaskPath; + } + + if (normalizedLastHydrated === normalizedTaskPath) { + Logger.debug('Same file hidrated'); + this.lastHydrated = ''; + return; + } + + this.lastHydrated = normalizedTaskPath; await this.container.virtualDrive.hydrateFile(task.path); ipcRenderer.send('CHECK_SYNC'); diff --git a/src/context/virtual-drive/folders/application/FolderPathUpdater.ts b/src/context/virtual-drive/folders/application/FolderPathUpdater.ts index a28d65966..94f6827e7 100644 --- a/src/context/virtual-drive/folders/application/FolderPathUpdater.ts +++ b/src/context/virtual-drive/folders/application/FolderPathUpdater.ts @@ -37,12 +37,6 @@ export class FolderPathUpdater { return await this.folderMover.run(folder, desiredPath); } - if (nameChanged) { - Logger.debug('about to rename'); - return await this.folderRenamer.run(folder, desiredPath); - } - - // throw new Error('No path change detected for folder path update'); - Logger.warn('No path change detected for folder path update'); + return await this.folderRenamer.run(folder, desiredPath); } } diff --git a/src/context/virtual-drive/folders/domain/Folder.ts b/src/context/virtual-drive/folders/domain/Folder.ts index bc916a2cd..bbee590cc 100644 --- a/src/context/virtual-drive/folders/domain/Folder.ts +++ b/src/context/virtual-drive/folders/domain/Folder.ts @@ -138,9 +138,6 @@ export class Folder extends AggregateRoot { rename(newPath: FolderPath) { const oldPath = this._path; - if (this._path.hasSameName(newPath)) { - throw new Error('Cannot rename a folder to the same name'); - } this._path = this._path.updateName(newPath.name()); this.updatedAt = new Date(); diff --git a/src/context/virtual-drive/folders/domain/OfflineFolder.ts b/src/context/virtual-drive/folders/domain/OfflineFolder.ts index d1be25396..3d72c4855 100644 --- a/src/context/virtual-drive/folders/domain/OfflineFolder.ts +++ b/src/context/virtual-drive/folders/domain/OfflineFolder.ts @@ -87,9 +87,6 @@ export class OfflineFolder extends AggregateRoot { rename(destination: FolderPath) { const oldPath = this._path; - if (this._path.hasSameName(destination)) { - throw new Error('Cannot rename a folder to the same name'); - } this._path = this._path.updateName(destination.name()); this.updatedAt = new Date(); From 97d7886e5ec0cca429c8aba8e932f1ee5453c34c Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 27 Aug 2024 10:19:38 -0300 Subject: [PATCH 03/18] fixed some bugs --- package.json | 2 +- release/app/package.json | 2 +- .../main/background-processes/sync-engine.ts | 3 +- src/apps/main/fordwardToWindows.ts | 5 +- .../main/remote-sync/RemoteSyncManager.ts | 1 + src/apps/main/remote-sync/handlers.ts | 23 ++---- src/apps/main/tray/handlers.ts | 6 +- .../pages/Widget/AnimationWrapper.tsx | 4 +- src/apps/sync-engine/BindingManager.ts | 74 ++++++++++++++----- .../controllers/AddController.ts | 4 - .../common/QueueManager.ts | 14 +++- .../files/FilesContainer.ts | 2 + .../dependency-injection/files/builder.ts | 4 + .../contents/domain/LocalFileContents.ts | 2 +- .../files/application/FileFinder.ts | 35 +++++++++ .../application/FilesPlaceholderDeleter.ts | 8 +- .../folders/application/FolderDeleter.ts | 1 - .../application/FolderPlaceholderDeleter.ts | 8 +- 18 files changed, 137 insertions(+), 61 deletions(-) create mode 100644 src/context/virtual-drive/files/application/FileFinder.ts diff --git a/package.json b/package.json index b0e5d30ce..0537388fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.0", + "version": "2.1.0-fix", "author": "Internxt ", "description": "Internxt Drive client UI", "license": "AGPL-3.0", diff --git a/release/app/package.json b/release/app/package.json index 33bb5678a..a3f057167 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.0", + "version": "2.1.0-fix", "description": "Internxt Drive client UI", "main": "./dist/main/main.js", "author": "Internxt ", diff --git a/src/apps/main/background-processes/sync-engine.ts b/src/apps/main/background-processes/sync-engine.ts index 319be48d1..cf2e2db0a 100644 --- a/src/apps/main/background-processes/sync-engine.ts +++ b/src/apps/main/background-processes/sync-engine.ts @@ -60,7 +60,6 @@ function scheduleHeathCheck() { .catch(() => { const warning = 'Health check failed, relaunching the worker'; Logger.warn(warning); - Sentry.captureMessage(warning); workerIsRunning = false; worker?.destroy(); if (attemptsAlreadyStarting >= 3) { @@ -72,7 +71,7 @@ function scheduleHeathCheck() { }); healthCheckSchedule = nodeSchedule.scheduleJob('*/20 * * * * *', async () => { - const workerIsPending = checkSyncEngineInProcess(15_000); + const workerIsPending = checkSyncEngineInProcess(5_000); Logger.debug( 'Health check', workerIsPending ? 'Worker is pending' : 'Worker is running' diff --git a/src/apps/main/fordwardToWindows.ts b/src/apps/main/fordwardToWindows.ts index 82019fc37..644c46abe 100644 --- a/src/apps/main/fordwardToWindows.ts +++ b/src/apps/main/fordwardToWindows.ts @@ -106,7 +106,6 @@ ipcMainDrive.on('FILE_CLONNED', (_, payload) => { ipcMainDrive.on('FILE_UPLOADING', (_, payload) => { const { nameWithExtension, processInfo } = payload; - setIsProcessing(true); broadcastToWindows('sync-info-update', { action: 'UPLOADING', name: nameWithExtension, @@ -116,7 +115,7 @@ ipcMainDrive.on('FILE_UPLOADING', (_, payload) => { ipcMainDrive.on('FILE_UPLOADED', (_, payload) => { const { nameWithExtension } = payload; - setIsProcessing(false); + // setIsProcessing(false); broadcastToWindows('sync-info-update', { action: 'UPLOADED', name: nameWithExtension, @@ -125,7 +124,7 @@ ipcMainDrive.on('FILE_UPLOADED', (_, payload) => { ipcMainDrive.on('FILE_CREATED', (_, payload) => { const { nameWithExtension } = payload; - setIsProcessing(false); + // setIsProcessing(false); broadcastToWindows('sync-info-update', { action: 'UPLOADED', diff --git a/src/apps/main/remote-sync/RemoteSyncManager.ts b/src/apps/main/remote-sync/RemoteSyncManager.ts index 797987e23..cb130787c 100644 --- a/src/apps/main/remote-sync/RemoteSyncManager.ts +++ b/src/apps/main/remote-sync/RemoteSyncManager.ts @@ -876,6 +876,7 @@ export class RemoteSyncManager { await this.db.folders.create({ ...remoteFolder, + type: remoteFolder.type ?? 'folder', parentId: remoteFolder.parentId ?? undefined, bucket: remoteFolder.bucket ?? undefined, }); diff --git a/src/apps/main/remote-sync/handlers.ts b/src/apps/main/remote-sync/handlers.ts index 9874957eb..478f609ab 100644 --- a/src/apps/main/remote-sync/handlers.ts +++ b/src/apps/main/remote-sync/handlers.ts @@ -18,7 +18,7 @@ import { debounce } from 'lodash'; import configStore from '../config'; import { setTrayStatus } from '../tray/tray'; -const SYNC_DEBOUNCE_DELAY = 3_000; +const SYNC_DEBOUNCE_DELAY = 500; let initialSyncReady = false; const driveFilesCollection = new DriveFilesCollection(); @@ -128,12 +128,10 @@ remoteSyncManager.onStatusChange((newStatus) => { }); remoteSyncManager.onStatusChange((newStatus) => { - if (newStatus === 'SYNCING') { - setTrayStatus('SYNCING'); - } if (newStatus === 'SYNCED') { - setTrayStatus('IDLE'); + return setTrayStatus('IDLE'); } + setTrayStatus('SYNCING'); }); ipcMain.handle('get-remote-sync-status', () => @@ -145,7 +143,7 @@ export async function updateRemoteSync(): Promise { // that we received the notification, but if we check // for new data we don't receive it Logger.info('Updating remote sync'); - const isSyncing = await checkSyncEngineInProcess(5_000); + const isSyncing = await checkSyncEngineInProcess(2_000); if (isSyncing) { Logger.info('Remote sync is already running'); return; @@ -158,7 +156,6 @@ export async function updateRemoteSync(): Promise { updateSyncEngine(); } export async function fallbackRemoteSync(): Promise { - await sleep(2_000); Logger.info('Fallback remote sync'); fallbackSyncEngine(); } @@ -184,7 +181,7 @@ ipcMain.handle('SEND_UPDATE_UNSYNC_FILE_IN_SYNC_ENGINE', async () => { ipcMain.on( 'UPDATE_UNSYNC_FILE_IN_SYNC_ENGINE', - async (_, filesPath: string[]) => { + async (_: unknown, filesPath: string[]) => { Logger.info('[SYNC ENGINE] update unSync files', filesPath); remoteSyncManager.setUnsyncFiles(filesPath); } @@ -195,15 +192,7 @@ const debouncedSynchronization = debounce(async () => { }, SYNC_DEBOUNCE_DELAY); eventBus.on('RECEIVED_REMOTE_CHANGES', async () => { - // Wait before checking for updates, could be possible - // that we received the notification, but if we check - // for new data we don't receive it Logger.info('Received remote changes event'); - const isSyncing = await checkSyncEngineInProcess(5_000); - if (isSyncing) { - Logger.info('Remote sync is already running'); - return; - } debouncedSynchronization(); }); @@ -216,7 +205,7 @@ eventBus.on('USER_LOGGED_IN', async () => { Logger.info('Last files sync at', lastFilesSyncAt); const folderId = lastFilesSyncAt ? undefined : userData?.root_folder_id; await startRemoteSync(folderId); - remoteSyncManager.isProcessRunning = false; + eventBus.emit('INITIAL_SYNC_READY'); } catch (error) { Logger.error('Error starting remote sync manager', error); if (error instanceof Error) reportError(error); diff --git a/src/apps/main/tray/handlers.ts b/src/apps/main/tray/handlers.ts index 0a6102554..196dc6b0a 100644 --- a/src/apps/main/tray/handlers.ts +++ b/src/apps/main/tray/handlers.ts @@ -72,9 +72,9 @@ ipcMainDrive.on('FILE_UPLOADING', () => { setTrayStatus('SYNCING'); }); -ipcMainDrive.on('FILE_UPLOADED', () => { - setTrayStatus('IDLE'); -}); +// ipcMainDrive.on('FILE_UPLOADED', () => { +// setTrayStatus('IDLE'); +// }); ipcMainDrive.on('FILE_UPLOAD_ERROR', () => { setTrayStatus('ALERT'); diff --git a/src/apps/renderer/pages/Widget/AnimationWrapper.tsx b/src/apps/renderer/pages/Widget/AnimationWrapper.tsx index 08a79bc3b..94f99eeb4 100644 --- a/src/apps/renderer/pages/Widget/AnimationWrapper.tsx +++ b/src/apps/renderer/pages/Widget/AnimationWrapper.tsx @@ -12,8 +12,8 @@ export function AnimationWrapper({ {children} diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index 1692ad6b0..a5f5cf6a5 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -19,6 +19,7 @@ import { runner } from '../utils/runner'; import { QueueManager } from './dependency-injection/common/QueueManager'; import { DependencyInjectionLogWatcherPath } from './dependency-injection/common/logEnginePath'; import configStore from '../main/config'; +import { FilePath } from '../../context/virtual-drive/files/domain/FilePath'; export type CallbackDownload = ( success: boolean, @@ -191,11 +192,35 @@ export class BindingsManager { // await callback(false, ''); fs.unlinkSync(path); - Logger.debug('[Fetch Data Callback] Finish...', path); + Logger.debug('[Fetch Data Error] Finish...', path); return; } fs.unlinkSync(path); + try { + await this.container.fileSyncStatusUpdater.run(file); + + const folderPath = file.path + .substring(0, file.path.lastIndexOf('/')) + .replace(/\\/g, '/'); + + const folderParentPath = new FilePath(folderPath); + + const folderParent = + await this.container.folderFinder.findFromFilePath( + folderParentPath + ); + + Logger.debug( + '[Fetch Data Callback] Preparing finish', + folderParent + ); + + await this.container.folderSyncStatusUpdater.run(folderParent); + } catch (error) { + Logger.error('Error updating sync status', error); + } + Logger.debug('[Fetch Data Callback] Finish...', path); } catch (error) { Logger.error(error); @@ -274,10 +299,22 @@ export class BindingsManager { } async watch() { - const queueManager = new QueueManager({ + const callbacks = { handleAdd: async (task: QueueItem) => { try { - Logger.debug('Path received from callback', task.path); + Logger.debug( + 'Path received from callback', + task.path.replace(/\\/g, '/') + ); + + const filePath = new FilePath(task.path.replace(/\\/g, '/')); + + const file = await this.container.fileFinder.findFromFilePath( + filePath + ); + + Logger.debug('File found', file); + const itemId = await this.controllers.addFile.execute(task.path); if (!itemId) { Logger.error('Error adding file' + task.path); @@ -292,7 +329,6 @@ export class BindingsManager { task.isFolder, true ); - ipcRenderer.send('CHECK_SYNC'); } catch (error) { Logger.error(`error adding file ${task.path}`); Logger.error(error); @@ -352,7 +388,14 @@ export class BindingsManager { Sentry.captureException(error); } }, - }); + }; + + const notify = { + onTaskSuccess: async () => ipcRendererSyncEngine.send('SYNCED'), + onTaskProcessing: async () => ipcRendererSyncEngine.send('SYNCING'), + }; + + const queueManager = new QueueManager(callbacks, notify); const logWatcherPath = DependencyInjectionLogWatcherPath.get(); this.container.virtualDrive.watchAndWait( this.paths.root, @@ -416,17 +459,15 @@ export class BindingsManager { try { const tree = await this.container.existingItemsTreeBuilder.run(); - // Delete all the placeholders that are not in the tree - await this.container?.filesPlaceholderDeleter?.run(tree.trashedFilesList); - await this.container?.folderPlaceholderDeleter?.run( - tree.trashedFoldersList - ); - - // Create all the placeholders that are in the tree - await this.container.folderPlaceholderUpdater.run(tree.folders); - await this.container.filesPlaceholderUpdater.run(tree.files); + await Promise.all([ + // Delete all the placeholders that are not in the tree + this.container?.filesPlaceholderDeleter?.run(tree.trashedFilesList), + this.container?.folderPlaceholderDeleter?.run(tree.trashedFoldersList), + // Create all the placeholders that are in the tree + this.container.folderPlaceholderUpdater.run(tree.folders), + this.container.filesPlaceholderUpdater.run(tree.files), + ]); ipcRendererSyncEngine.send('SYNCED'); - ipcRenderer.send('CHECK_SYNC'); } catch (error) { Logger.error('[SYNC ENGINE] ', error); Sentry.captureException(error); @@ -441,14 +482,11 @@ export class BindingsManager { async polling(): Promise { try { Logger.info('[SYNC ENGINE] Monitoring polling...'); - ipcRendererSyncEngine.send('SYNCING'); const fileInPendingPaths = (await this.container.virtualDrive.getPlaceholderWithStatePending()) as Array; Logger.info('[SYNC ENGINE] fileInPendingPaths', fileInPendingPaths); await this.container.fileSyncOrchestrator.run(fileInPendingPaths); - ipcRendererSyncEngine.send('SYNCED'); - ipcRenderer.send('CHECK_SYNC'); } catch (error) { Logger.error('[SYNC ENGINE] Polling', error); Sentry.captureException(error); diff --git a/src/apps/sync-engine/callbacks-controllers/controllers/AddController.ts b/src/apps/sync-engine/callbacks-controllers/controllers/AddController.ts index 231aeaa9c..e1b210e76 100644 --- a/src/apps/sync-engine/callbacks-controllers/controllers/AddController.ts +++ b/src/apps/sync-engine/callbacks-controllers/controllers/AddController.ts @@ -3,7 +3,6 @@ import { FileCreationOrchestrator } from '../../../../context/virtual-drive/boun import { createFilePlaceholderId } from '../../../../context/virtual-drive/files/domain/PlaceholderId'; import { FolderCreator } from '../../../../context/virtual-drive/folders/application/FolderCreator'; import { OfflineFolderCreator } from '../../../../context/virtual-drive/folders/application/Offline/OfflineFolderCreator'; -import { createFolderPlaceholderId } from '../../../../context/virtual-drive/folders/domain/FolderPlaceholderId'; import { OfflineFolder } from '../../../../context/virtual-drive/folders/domain/OfflineFolder'; import { AbsolutePathToRelativeConverter } from '../../../../context/virtual-drive/shared/application/AbsolutePathToRelativeConverter'; import { PlatformPathConverter } from '../../../../context/virtual-drive/shared/application/PlatformPathConverter'; @@ -11,10 +10,7 @@ import { PathTypeChecker } from '../../../shared/fs/PathTypeChecker '; import { CallbackController } from './CallbackController'; import { FolderNotFoundError } from '../../../../context/virtual-drive/folders/domain/errors/FolderNotFoundError'; import { Folder } from '../../../../context/virtual-drive/folders/domain/Folder'; -import { ipcRenderer } from 'electron'; -import { FileAddedCallback } from '../../BindingManager'; import * as Sentry from '@sentry/electron/renderer'; - export class AddController extends CallbackController { // Gets called when: // - a file has been added diff --git a/src/apps/sync-engine/dependency-injection/common/QueueManager.ts b/src/apps/sync-engine/dependency-injection/common/QueueManager.ts index 6ee17fd10..52683949f 100644 --- a/src/apps/sync-engine/dependency-injection/common/QueueManager.ts +++ b/src/apps/sync-engine/dependency-injection/common/QueueManager.ts @@ -5,7 +5,6 @@ import { HandleActions, } from 'virtual-drive/dist'; import Logger from 'electron-log'; -import { sleep } from '../../../main/util'; export type QueueHandler = { handleAdd: HandleAction; @@ -15,6 +14,11 @@ export type QueueHandler = { handleChangeSize: HandleAction; }; +export type QueueManagerCallback = { + onTaskSuccess: () => Promise; + onTaskProcessing: () => Promise; +}; + export class QueueManager implements IQueueManager { private queues: { [key: string]: QueueItem[] } = { add: [], @@ -32,9 +36,11 @@ export class QueueManager implements IQueueManager { changeSize: false, }; + private notify: QueueManagerCallback; + actions: HandleActions; - constructor(handlers: QueueHandler) { + constructor(handlers: QueueHandler, notify: QueueManagerCallback) { this.actions = { add: handlers.handleAdd, hydrate: handlers.handleHydrate, @@ -42,6 +48,7 @@ export class QueueManager implements IQueueManager { changeSize: handlers.handleChangeSize, change: handlers.handleChange || (() => Promise.resolve()), }; + this.notify = notify; } public enqueue(task: QueueItem): void { @@ -85,6 +92,7 @@ export class QueueManager implements IQueueManager { const task = this.queues[type].shift(); if (task) { Logger.debug(`Processing ${type} task: ${JSON.stringify(task)}`); + Logger.debug(`Tasks length: ${this.queues[type].length}`); try { await this.actions[task.type](task); } catch (error) { @@ -97,6 +105,8 @@ export class QueueManager implements IQueueManager { public async processAll(): Promise { const taskTypes = Object.keys(this.queues); + await this.notify.onTaskProcessing(); await Promise.all(taskTypes.map((type) => this.processQueue(type))); + await this.notify.onTaskSuccess(); } } diff --git a/src/apps/sync-engine/dependency-injection/files/FilesContainer.ts b/src/apps/sync-engine/dependency-injection/files/FilesContainer.ts index c692474e1..b8555e7dc 100644 --- a/src/apps/sync-engine/dependency-injection/files/FilesContainer.ts +++ b/src/apps/sync-engine/dependency-injection/files/FilesContainer.ts @@ -16,10 +16,12 @@ import { FileSyncStatusUpdater } from '../../../../context/virtual-drive/files/a import { FileCheckerStatusInRoot } from '../../../../context/virtual-drive/files/application/FileCheckerStatusInRoot'; import { FilesPlaceholderDeleter } from '../../../../context/virtual-drive/files/application/FilesPlaceholderDeleter'; import { FileIdentityUpdater } from '../../../../context/virtual-drive/files/application/FileIndetityUpdater'; +import { FileFinder } from '../../../../context/virtual-drive/files/application/FileFinder'; export interface FilesContainer { fileFinderByContentsId: FileFinderByContentsId; fileDeleter: FileDeleter; + fileFinder: FileFinder; fileFolderContainerDetector: FileFolderContainerDetector; filePathUpdater: FilePathUpdater; fileCreator: FileCreator; diff --git a/src/apps/sync-engine/dependency-injection/files/builder.ts b/src/apps/sync-engine/dependency-injection/files/builder.ts index 4cebc5297..37684a036 100644 --- a/src/apps/sync-engine/dependency-injection/files/builder.ts +++ b/src/apps/sync-engine/dependency-injection/files/builder.ts @@ -1,3 +1,4 @@ +import { FileFinder } from './../../../../context/virtual-drive/files/application/FileFinder'; import crypt from '../../../../context/shared/infrastructure/crypt'; import { ipcRendererSyncEngine } from '../../ipcRendererSyncEngine'; import { DependencyInjectionEventBus } from '../common/eventBus'; @@ -92,6 +93,8 @@ export async function buildFilesContainer( eventBus ); + const fileFinder = new FileFinder(repository); + const fileCreator = new FileCreator( remoteFileSystem, repository, @@ -163,6 +166,7 @@ export async function buildFilesContainer( const container: FilesContainer = { fileFinderByContentsId, + fileFinder, fileDeleter, filePathUpdater, fileCreator, diff --git a/src/context/virtual-drive/contents/domain/LocalFileContents.ts b/src/context/virtual-drive/contents/domain/LocalFileContents.ts index 95a5c24ea..1094dc04d 100644 --- a/src/context/virtual-drive/contents/domain/LocalFileContents.ts +++ b/src/context/virtual-drive/contents/domain/LocalFileContents.ts @@ -33,7 +33,7 @@ export class LocalFileContents extends AggregateRoot { } public get nameWithExtension(): string { - return this.name + (this.extension.length >= 0 ? '.' + this.extension : ''); + return this.name + (this.extension?.length ? '.' + this.extension : ''); } public get size(): number { diff --git a/src/context/virtual-drive/files/application/FileFinder.ts b/src/context/virtual-drive/files/application/FileFinder.ts new file mode 100644 index 000000000..b5997ae39 --- /dev/null +++ b/src/context/virtual-drive/files/application/FileFinder.ts @@ -0,0 +1,35 @@ +import { FilePath } from '../../files/domain/FilePath'; +import { FileNotFoundError } from '../domain/errors/FileNotFoundError'; +import { File } from '../domain/File'; +import { FileRepository } from '../domain/FileRepository'; + +export class FileFinder { + constructor(private readonly repository: FileRepository) {} + + run(path: string): File { + const file = this.repository.searchByPartial({ path }); + + if (!file) { + throw new FileNotFoundError(path); + } + + return file; + } + + findFromFilePath(path: FilePath): File { + const file = this.repository.searchByPartial({ path: path.dirname() }); + + if (!file) { + throw new FileNotFoundError(path.dirname()); + } + + return file; + } + findFromUuid(uuid: File['uuid']): File { + const folder = this.repository.searchByPartial({ uuid }); + if (!folder) { + throw new Error('Folder not found'); + } + return folder; + } +} diff --git a/src/context/virtual-drive/files/application/FilesPlaceholderDeleter.ts b/src/context/virtual-drive/files/application/FilesPlaceholderDeleter.ts index 845815ad8..5a5bae0c2 100644 --- a/src/context/virtual-drive/files/application/FilesPlaceholderDeleter.ts +++ b/src/context/virtual-drive/files/application/FilesPlaceholderDeleter.ts @@ -49,8 +49,10 @@ export class FilesPlaceholderDeleter { } async run(remotes: File[]): Promise { - for (const remote of remotes) { - await this.delete(remote); - } + await Promise.all( + remotes.map(async (remote) => { + await this.delete(remote); + }) + ); } } diff --git a/src/context/virtual-drive/folders/application/FolderDeleter.ts b/src/context/virtual-drive/folders/application/FolderDeleter.ts index b85155e4b..d829086b1 100644 --- a/src/context/virtual-drive/folders/application/FolderDeleter.ts +++ b/src/context/virtual-drive/folders/application/FolderDeleter.ts @@ -45,7 +45,6 @@ export class FolderDeleter { await this.repository.update(folder); } catch (error: unknown) { Logger.error(`Error deleting the folder ${folder.name}: `, error); - Sentry.captureException(error); this.local.createPlaceHolder(folder); } } diff --git a/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts b/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts index 5a3cfc40a..1a821e7ba 100644 --- a/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts +++ b/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts @@ -70,8 +70,10 @@ export class FolderPlaceholderDeleter { } async run(remotes: Folder[]): Promise { - for (const remote of remotes) { - await this.delete(remote); - } + await Promise.all( + remotes.map(async (remote) => { + await this.delete(remote); + }) + ); } } From 9ab230512ca6363206647b4ad988cb5e6efb2fff Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 28 Aug 2024 10:41:57 -0300 Subject: [PATCH 04/18] add persist queueManager --- package.json | 2 +- release/app/package.json | 2 +- .../main/background-processes/sync-engine.ts | 4 +- src/apps/main/virtual-root-folder/service.ts | 7 +++ src/apps/sync-engine/BindingManager.ts | 15 +++++- .../common/QueueManager.ts | 51 ++++++++++++++++++- .../files/application/FileSyncronizer.ts | 4 -- .../infrastructure/HttpRemoteFileSystem.ts | 2 +- 8 files changed, 75 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 0537388fd..bad57b139 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.0-fix", + "version": "2.1.1", "author": "Internxt ", "description": "Internxt Drive client UI", "license": "AGPL-3.0", diff --git a/release/app/package.json b/release/app/package.json index a3f057167..2afbcc492 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.0-fix", + "version": "2.1.1", "description": "Internxt Drive client UI", "main": "./dist/main/main.js", "author": "Internxt ", diff --git a/src/apps/main/background-processes/sync-engine.ts b/src/apps/main/background-processes/sync-engine.ts index cf2e2db0a..358e47ca6 100644 --- a/src/apps/main/background-processes/sync-engine.ts +++ b/src/apps/main/background-processes/sync-engine.ts @@ -31,7 +31,7 @@ async function healthCheck() { resolve(); }); - const millisecondsToWait = 5_000; + const millisecondsToWait = 10_000; setTimeout(() => { reject( @@ -70,7 +70,7 @@ function scheduleHeathCheck() { spawnSyncEngineWorker(); }); - healthCheckSchedule = nodeSchedule.scheduleJob('*/20 * * * * *', async () => { + healthCheckSchedule = nodeSchedule.scheduleJob('*/40 * * * * *', async () => { const workerIsPending = checkSyncEngineInProcess(5_000); Logger.debug( 'Health check', diff --git a/src/apps/main/virtual-root-folder/service.ts b/src/apps/main/virtual-root-folder/service.ts index a61fb26d1..298abf591 100644 --- a/src/apps/main/virtual-root-folder/service.ts +++ b/src/apps/main/virtual-root-folder/service.ts @@ -54,9 +54,16 @@ function setSyncRoot(pathname: string): void { 'watcher-win.txt' ); + const persistQueueManager = path.join( + app.getPath('appData'), + 'internxt-drive', + 'queue-manager.json' + ); + configStore.set('logEnginePath', logEnginePath); configStore.set('logWatcherPath', logWatcherPath); configStore.set('syncRoot', pathNameWithSepInTheEnd); + configStore.set('persistQueueManagerPath', persistQueueManager); configStore.set('lastSavedListing', ''); } diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index a5f5cf6a5..36e9977dd 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -359,7 +359,6 @@ export class BindingsManager { this.lastHydrated = normalizedTaskPath; await this.container.virtualDrive.hydrateFile(task.path); - ipcRenderer.send('CHECK_SYNC'); Logger.debug('[Handle Hydrate Callback] Finish begins', task.path); } catch (error) { @@ -395,7 +394,17 @@ export class BindingsManager { onTaskProcessing: async () => ipcRendererSyncEngine.send('SYNCING'), }; - const queueManager = new QueueManager(callbacks, notify); + const persistQueueManager: string = configStore.get( + 'persistQueueManagerPath' + ); + + Logger.debug('persistQueueManager', persistQueueManager); + + const queueManager = new QueueManager( + callbacks, + notify, + persistQueueManager + ); const logWatcherPath = DependencyInjectionLogWatcherPath.get(); this.container.virtualDrive.watchAndWait( this.paths.root, @@ -481,6 +490,7 @@ export class BindingsManager { async polling(): Promise { try { + ipcRendererSyncEngine.send('SYNCING'); Logger.info('[SYNC ENGINE] Monitoring polling...'); const fileInPendingPaths = (await this.container.virtualDrive.getPlaceholderWithStatePending()) as Array; @@ -491,6 +501,7 @@ export class BindingsManager { Logger.error('[SYNC ENGINE] Polling', error); Sentry.captureException(error); } + ipcRendererSyncEngine.send('SYNCED'); } async getFileInSyncPending(): Promise { try { diff --git a/src/apps/sync-engine/dependency-injection/common/QueueManager.ts b/src/apps/sync-engine/dependency-injection/common/QueueManager.ts index 52683949f..a4c62aa49 100644 --- a/src/apps/sync-engine/dependency-injection/common/QueueManager.ts +++ b/src/apps/sync-engine/dependency-injection/common/QueueManager.ts @@ -5,6 +5,8 @@ import { HandleActions, } from 'virtual-drive/dist'; import Logger from 'electron-log'; +import fs from 'fs'; +import path from 'path'; export type QueueHandler = { handleAdd: HandleAction; @@ -38,9 +40,15 @@ export class QueueManager implements IQueueManager { private notify: QueueManagerCallback; + private persistPath: string; + actions: HandleActions; - constructor(handlers: QueueHandler, notify: QueueManagerCallback) { + constructor( + handlers: QueueHandler, + notify: QueueManagerCallback, + persistPath: string + ) { this.actions = { add: handlers.handleAdd, hydrate: handlers.handleHydrate, @@ -49,6 +57,45 @@ export class QueueManager implements IQueueManager { change: handlers.handleChange || (() => Promise.resolve()), }; this.notify = notify; + this.persistPath = persistPath; + // creamos el archivo de persistencia si no existe + if (!fs.existsSync(this.persistPath)) { + fs.writeFileSync(this.persistPath, JSON.stringify(this.queues)); + } else { + this.loadQueueStateFromFile(); + } + } + private saveQueueStateToFile(): void { + if (!this.persistPath) return; + + fs.writeFileSync( + this.persistPath, + JSON.stringify( + { + add: [], + hydrate: this.queues.hydrate, + dehydrate: this.queues.dehydrate, + change: [], + changeSize: [], + }, + null, + 2 + ) + ); + } + + private loadQueueStateFromFile(): void { + Logger.debug('Loading queue state from file:' + this.persistPath); + if (this.persistPath) { + // Si el archivo no existe, se crea y se guarda el estado inicial de las colas. + if (!fs.existsSync(this.persistPath)) { + this.saveQueueStateToFile(); // Guarda el estado inicial en el archivo + } + + // Si el archivo existe, carga los datos desde él. + const data = fs.readFileSync(this.persistPath, 'utf-8'); + this.queues = JSON.parse(data); + } } public enqueue(task: QueueItem): void { @@ -62,6 +109,7 @@ export class QueueManager implements IQueueManager { } this.queues[task.type].push(task); this.sortQueue(task.type); + this.saveQueueStateToFile(); if (!this.isProcessing[task.type]) { this.processQueue(task.type); } @@ -90,6 +138,7 @@ export class QueueManager implements IQueueManager { this.isProcessing[type] = true; while (this.queues[type].length > 0) { const task = this.queues[type].shift(); + this.saveQueueStateToFile(); if (task) { Logger.debug(`Processing ${type} task: ${JSON.stringify(task)}`); Logger.debug(`Tasks length: ${this.queues[type].length}`); diff --git a/src/context/virtual-drive/files/application/FileSyncronizer.ts b/src/context/virtual-drive/files/application/FileSyncronizer.ts index 63eb68b4b..ae76f6cb8 100644 --- a/src/context/virtual-drive/files/application/FileSyncronizer.ts +++ b/src/context/virtual-drive/files/application/FileSyncronizer.ts @@ -91,7 +91,6 @@ export class FileSyncronizer { attemps = 3 ) => { try { - await new Promise((resolve) => setTimeout(resolve, 2000)); const fileContents = await upload(posixRelativePath); const createdFile = await this.fileCreator.run(filePath, fileContents); await this.convertAndUpdateSyncStatus(createdFile); @@ -101,7 +100,6 @@ export class FileSyncronizer { await this.createFolderFather(posixRelativePath); } if (attemps > 0) { - await new Promise((resolve) => setTimeout(resolve, 2000)); await this.retryCreation( posixRelativePath, filePath, @@ -123,7 +121,6 @@ export class FileSyncronizer { const posixDir = PlatformPathConverter.getFatherPathPosix(posixRelativePath); try { - await new Promise((resolve) => setTimeout(resolve, 4000)); await this.runFolderCreator(posixDir); } catch (error) { Logger.error('Error creating folder father creation:', error); @@ -159,7 +156,6 @@ export class FileSyncronizer { private retryFolderCreation = async (posixDir: string, attemps = 3) => { try { - await new Promise((resolve) => setTimeout(resolve, 4000)); await this.runFolderCreator(posixDir); } catch (error) { Logger.error('Error creating folder father creation:', error); diff --git a/src/context/virtual-drive/folders/infrastructure/HttpRemoteFileSystem.ts b/src/context/virtual-drive/folders/infrastructure/HttpRemoteFileSystem.ts index 6cd732d9d..ece8186c6 100644 --- a/src/context/virtual-drive/folders/infrastructure/HttpRemoteFileSystem.ts +++ b/src/context/virtual-drive/folders/infrastructure/HttpRemoteFileSystem.ts @@ -52,7 +52,7 @@ export class HttpRemoteFileSystem implements RemoteFileSystem { path: offline.path.value, status: FolderStatuses.EXISTS, }; - } catch (error: any) { + } catch (error: unknown) { Logger.error('[FOLDER FILE SYSTEM] Error creating folder', error); Sentry.captureException(error); if (axios.isAxiosError(error)) { From eb5c46e8707fe30ff5d75c31c542ef2503c198e9 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Thu, 29 Aug 2024 13:42:19 -0300 Subject: [PATCH 05/18] delete queue manager persist after logout --- src/apps/main/remote-sync/handlers.ts | 9 ++++++--- src/apps/sync-engine/BindingManager.ts | 8 ++++++++ .../dependency-injection/common/QueueManager.ts | 15 +++++++++++---- .../files/application/FilesPlaceholderUpdater.ts | 2 ++ .../files/domain/file-systems/LocalFileSystem.ts | 2 +- .../infrastructure/NodeWinLocalFileSystem.ts | 4 ++-- .../folders/application/FolderDeleter.ts | 4 ++-- .../application/FolderPlaceholderConverter.ts | 4 ++-- .../application/FolderPlaceholderDeleter.ts | 4 ++-- .../application/FolderSyncStatusUpdater.ts | 6 +++--- .../application/FoldersFatherSyncStatusUpdater.ts | 6 +++--- .../application/FoldersPlaceholderCreator.ts | 4 ++-- .../application/UpdatePlaceholderFolder.ts | 6 ++++-- .../{LocalFileSystem.ts => LocalFolderSystem.ts} | 4 ++-- .../infrastructure/NodeWinLocalFileSystem.ts | 8 ++++---- .../__mocks__/FolderLocalFileSystemMock.ts | 4 ++-- 16 files changed, 56 insertions(+), 34 deletions(-) rename src/context/virtual-drive/folders/domain/file-systems/{LocalFileSystem.ts => LocalFolderSystem.ts} (75%) diff --git a/src/apps/main/remote-sync/handlers.ts b/src/apps/main/remote-sync/handlers.ts index 478f609ab..f9dde2927 100644 --- a/src/apps/main/remote-sync/handlers.ts +++ b/src/apps/main/remote-sync/handlers.ts @@ -128,10 +128,13 @@ remoteSyncManager.onStatusChange((newStatus) => { }); remoteSyncManager.onStatusChange((newStatus) => { - if (newStatus === 'SYNCED') { - return setTrayStatus('IDLE'); + if (newStatus === 'SYNCING') { + return setTrayStatus('SYNCING'); } - setTrayStatus('SYNCING'); + if (newStatus === 'SYNC_FAILED') { + return setTrayStatus('ALERT'); + } + setTrayStatus('IDLE'); }); ipcMain.handle('get-remote-sync-status', () => diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index 36e9977dd..c874847ea 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -36,6 +36,7 @@ export class BindingsManager { private progressBuffer = 0; private controllers: IControllers; + private queueManager: QueueManager | null = null; private lastHydrated = ''; constructor( @@ -405,6 +406,7 @@ export class BindingsManager { notify, persistQueueManager ); + this.queueManager = queueManager; const logWatcherPath = DependencyInjectionLogWatcherPath.get(); this.container.virtualDrive.watchAndWait( this.paths.root, @@ -461,6 +463,12 @@ export class BindingsManager { // }); } + async cleanQueue() { + if (this.queueManager) { + await this.queueManager.clearQueue(); + } + } + async update() { Logger.info('[SYNC ENGINE]: Updating placeholders'); ipcRendererSyncEngine.send('SYNCING'); diff --git a/src/apps/sync-engine/dependency-injection/common/QueueManager.ts b/src/apps/sync-engine/dependency-injection/common/QueueManager.ts index a4c62aa49..fd9e0c8a3 100644 --- a/src/apps/sync-engine/dependency-injection/common/QueueManager.ts +++ b/src/apps/sync-engine/dependency-injection/common/QueueManager.ts @@ -58,7 +58,6 @@ export class QueueManager implements IQueueManager { }; this.notify = notify; this.persistPath = persistPath; - // creamos el archivo de persistencia si no existe if (!fs.existsSync(this.persistPath)) { fs.writeFileSync(this.persistPath, JSON.stringify(this.queues)); } else { @@ -87,16 +86,24 @@ export class QueueManager implements IQueueManager { private loadQueueStateFromFile(): void { Logger.debug('Loading queue state from file:' + this.persistPath); if (this.persistPath) { - // Si el archivo no existe, se crea y se guarda el estado inicial de las colas. if (!fs.existsSync(this.persistPath)) { - this.saveQueueStateToFile(); // Guarda el estado inicial en el archivo + this.saveQueueStateToFile(); } - // Si el archivo existe, carga los datos desde él. const data = fs.readFileSync(this.persistPath, 'utf-8'); this.queues = JSON.parse(data); } } + public clearQueue(): void { + this.queues = { + add: [], + hydrate: [], + dehydrate: [], + change: [], + changeSize: [], + }; + this.saveQueueStateToFile(); + } public enqueue(task: QueueItem): void { Logger.debug(`Task enqueued: ${JSON.stringify(task)}`); diff --git a/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts b/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts index 3e672c5e6..aac016a3a 100644 --- a/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts +++ b/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts @@ -77,6 +77,8 @@ export class FilesPlaceholderUpdater { ); await fs.unlink(win32AbsolutePath); } + + await this.localFileSystem.updateSyncStatus(remote, false); } async run(remotes: Array): Promise { diff --git a/src/context/virtual-drive/files/domain/file-systems/LocalFileSystem.ts b/src/context/virtual-drive/files/domain/file-systems/LocalFileSystem.ts index 5090349a2..4b03c3de3 100644 --- a/src/context/virtual-drive/files/domain/file-systems/LocalFileSystem.ts +++ b/src/context/virtual-drive/files/domain/file-systems/LocalFileSystem.ts @@ -8,7 +8,7 @@ export interface LocalFileSystem { getLocalFileId(file: File): Promise<`${string}-${string}`>; - updateSyncStatus(file: File): Promise; + updateSyncStatus(file: File, status: boolean): Promise; getFileIdentity(path: File['path']): Promise; diff --git a/src/context/virtual-drive/files/infrastructure/NodeWinLocalFileSystem.ts b/src/context/virtual-drive/files/infrastructure/NodeWinLocalFileSystem.ts index 3c3c51863..6a3d56951 100644 --- a/src/context/virtual-drive/files/infrastructure/NodeWinLocalFileSystem.ts +++ b/src/context/virtual-drive/files/infrastructure/NodeWinLocalFileSystem.ts @@ -55,11 +55,11 @@ export class NodeWinLocalFileSystem implements LocalFileSystem { await this.virtualDrive.deleteFileSyncRoot(path); } - async updateSyncStatus(file: File): Promise { + async updateSyncStatus(file: File, status = true): Promise { const win32AbsolutePath = this.relativePathToAbsoluteConverter.run( file.path ); - return this.virtualDrive.updateSyncStatus(win32AbsolutePath, false); + return this.virtualDrive.updateSyncStatus(win32AbsolutePath, false, status); } async convertToPlaceholder(file: File): Promise { diff --git a/src/context/virtual-drive/folders/application/FolderDeleter.ts b/src/context/virtual-drive/folders/application/FolderDeleter.ts index d829086b1..2eede9b9e 100644 --- a/src/context/virtual-drive/folders/application/FolderDeleter.ts +++ b/src/context/virtual-drive/folders/application/FolderDeleter.ts @@ -5,13 +5,13 @@ import { FolderNotFoundError } from '../domain/errors/FolderNotFoundError'; import { AllParentFoldersStatusIsExists } from './AllParentFoldersStatusIsExists'; import { FolderRepository } from '../domain/FolderRepository'; import { RemoteFileSystem } from '../domain/file-systems/RemoteFileSystem'; -import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem'; +import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; export class FolderDeleter { constructor( private readonly repository: FolderRepository, private readonly remote: RemoteFileSystem, - private readonly local: LocalFileSystem, + private readonly local: LocalFolderSystem, private readonly allParentFoldersStatusIsExists: AllParentFoldersStatusIsExists ) {} diff --git a/src/context/virtual-drive/folders/application/FolderPlaceholderConverter.ts b/src/context/virtual-drive/folders/application/FolderPlaceholderConverter.ts index b3d84f30c..d45e35ca8 100644 --- a/src/context/virtual-drive/folders/application/FolderPlaceholderConverter.ts +++ b/src/context/virtual-drive/folders/application/FolderPlaceholderConverter.ts @@ -1,8 +1,8 @@ import { Folder } from '../domain/Folder'; -import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem'; +import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; export class FolderPlaceholderConverter { - constructor(private readonly localFileSystem: LocalFileSystem) {} + constructor(private readonly localFileSystem: LocalFolderSystem) {} async run(folder: Folder) { await this.localFileSystem.convertToPlaceholder(folder); diff --git a/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts b/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts index 1a821e7ba..410ffb110 100644 --- a/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts +++ b/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts @@ -2,7 +2,7 @@ import { RelativePathToAbsoluteConverter } from '../../shared/application/Relati import { Folder } from '../domain/Folder'; import { FolderStatuses } from '../domain/FolderStatus'; import { RemoteFileSystem } from '../domain/file-systems/RemoteFileSystem'; -import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem'; +import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; import Logger from 'electron-log'; import { sleep } from '../../../../apps/main/util'; @@ -10,7 +10,7 @@ export class FolderPlaceholderDeleter { constructor( private readonly relativePathToAbsoluteConverter: RelativePathToAbsoluteConverter, private readonly remoteFileSystem: RemoteFileSystem, - private readonly local: LocalFileSystem + private readonly local: LocalFolderSystem ) {} private async hasToBeDeleted(remote: Folder): Promise { diff --git a/src/context/virtual-drive/folders/application/FolderSyncStatusUpdater.ts b/src/context/virtual-drive/folders/application/FolderSyncStatusUpdater.ts index d333caf4c..daa8b2942 100644 --- a/src/context/virtual-drive/folders/application/FolderSyncStatusUpdater.ts +++ b/src/context/virtual-drive/folders/application/FolderSyncStatusUpdater.ts @@ -1,10 +1,10 @@ import { Folder } from '../domain/Folder'; -import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem'; +import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; export class FolderSyncStatusUpdater { - constructor(private readonly localFileSystem: LocalFileSystem) {} + constructor(private readonly localFileSystem: LocalFolderSystem) {} async run(folder: Folder) { - await this.localFileSystem.updateSyncStatus(folder); + await this.localFileSystem.updateSyncStatus(folder, true); } } diff --git a/src/context/virtual-drive/folders/application/FoldersFatherSyncStatusUpdater.ts b/src/context/virtual-drive/folders/application/FoldersFatherSyncStatusUpdater.ts index 6b94883df..4286e2d86 100644 --- a/src/context/virtual-drive/folders/application/FoldersFatherSyncStatusUpdater.ts +++ b/src/context/virtual-drive/folders/application/FoldersFatherSyncStatusUpdater.ts @@ -2,12 +2,12 @@ import { File } from '../../files/domain/File'; import { PlatformPathConverter } from '../../shared/application/PlatformPathConverter'; import { Folder } from '../domain/Folder'; import { FolderRepository } from '../domain/FolderRepository'; -import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem'; +import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; import Logger from 'electron-log'; export class FoldersFatherSyncStatusUpdater { constructor( - private readonly localFileSystem: LocalFileSystem, + private readonly localFileSystem: LocalFolderSystem, private readonly repository: FolderRepository ) {} @@ -23,7 +23,7 @@ export class FoldersFatherSyncStatusUpdater { const folder = await this.repository.searchByPartial({ path: posixDir }); if (folder) { Logger.debug(`Updating sync status for ${folder.path}`); - await this.localFileSystem.updateSyncStatus(folder); + await this.localFileSystem.updateSyncStatus(folder, true); } this.update(posixDir); } diff --git a/src/context/virtual-drive/folders/application/FoldersPlaceholderCreator.ts b/src/context/virtual-drive/folders/application/FoldersPlaceholderCreator.ts index 62bbf1fb5..855b5a9f2 100644 --- a/src/context/virtual-drive/folders/application/FoldersPlaceholderCreator.ts +++ b/src/context/virtual-drive/folders/application/FoldersPlaceholderCreator.ts @@ -1,8 +1,8 @@ import { Folder } from '../domain/Folder'; -import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem'; +import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; export class FoldersPlaceholderCreator { - constructor(private readonly local: LocalFileSystem) {} + constructor(private readonly local: LocalFolderSystem) {} async run(folders: Array): Promise { const createPromises = folders.map((folder) => diff --git a/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts b/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts index 13b6a5da2..78617c8b4 100644 --- a/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts +++ b/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts @@ -5,12 +5,12 @@ import Logger from 'electron-log'; import path from 'path'; import { FolderStatuses } from '../domain/FolderStatus'; import { FolderRepository } from '../domain/FolderRepository'; -import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem'; import * as Sentry from '@sentry/electron/renderer'; +import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; export class FolderPlaceholderUpdater { constructor( private readonly repository: FolderRepository, - private readonly local: LocalFileSystem, + private readonly local: LocalFolderSystem, private readonly relativePathToAbsoluteConverter: RelativePathToAbsoluteConverter ) {} @@ -135,6 +135,8 @@ export class FolderPlaceholderUpdater { await fs.rm(win32AbsolutePath, { recursive: true }); return; } + + await this.local.updateSyncStatus(remote, false); } async run(remotes: Array): Promise { diff --git a/src/context/virtual-drive/folders/domain/file-systems/LocalFileSystem.ts b/src/context/virtual-drive/folders/domain/file-systems/LocalFolderSystem.ts similarity index 75% rename from src/context/virtual-drive/folders/domain/file-systems/LocalFileSystem.ts rename to src/context/virtual-drive/folders/domain/file-systems/LocalFolderSystem.ts index c9b140306..ebed48c82 100644 --- a/src/context/virtual-drive/folders/domain/file-systems/LocalFileSystem.ts +++ b/src/context/virtual-drive/folders/domain/file-systems/LocalFolderSystem.ts @@ -1,9 +1,9 @@ import { Folder } from '../Folder'; -export interface LocalFileSystem { +export interface LocalFolderSystem { createPlaceHolder(folder: Folder): Promise; - updateSyncStatus(folder: Folder): Promise; + updateSyncStatus(folder: Folder, status: boolean): Promise; convertToPlaceholder(folder: Folder): Promise; diff --git a/src/context/virtual-drive/folders/infrastructure/NodeWinLocalFileSystem.ts b/src/context/virtual-drive/folders/infrastructure/NodeWinLocalFileSystem.ts index 39ca67e4a..5dc7a4853 100644 --- a/src/context/virtual-drive/folders/infrastructure/NodeWinLocalFileSystem.ts +++ b/src/context/virtual-drive/folders/infrastructure/NodeWinLocalFileSystem.ts @@ -1,10 +1,10 @@ import { VirtualDrive } from 'virtual-drive/dist'; import { Folder } from '../domain/Folder'; import { FolderStatuses } from '../domain/FolderStatus'; -import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem'; +import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; import { RelativePathToAbsoluteConverter } from '../../shared/application/RelativePathToAbsoluteConverter'; -export class NodeWinLocalFileSystem implements LocalFileSystem { +export class NodeWinLocalFileSystem implements LocalFolderSystem { constructor( private readonly virtualDrive: VirtualDrive, private readonly relativePathToAbsoluteConverter: RelativePathToAbsoluteConverter @@ -26,12 +26,12 @@ export class NodeWinLocalFileSystem implements LocalFileSystem { ); } - async updateSyncStatus(folder: Folder): Promise { + async updateSyncStatus(folder: Folder, status = true): Promise { const folderPath = `${folder.path}/`; const win32AbsolutePath = this.relativePathToAbsoluteConverter.run(folderPath); - return this.virtualDrive.updateSyncStatus(win32AbsolutePath, true); + return this.virtualDrive.updateSyncStatus(win32AbsolutePath, true, status); } async getFileIdentity(path: File['path']): Promise { diff --git a/tests/context/virtual-drive/folders/__mocks__/FolderLocalFileSystemMock.ts b/tests/context/virtual-drive/folders/__mocks__/FolderLocalFileSystemMock.ts index f494e88bd..2028559ee 100644 --- a/tests/context/virtual-drive/folders/__mocks__/FolderLocalFileSystemMock.ts +++ b/tests/context/virtual-drive/folders/__mocks__/FolderLocalFileSystemMock.ts @@ -1,7 +1,7 @@ import { Folder } from '../../../../../src/context/virtual-drive/folders/domain/Folder'; -import { LocalFileSystem } from '../../../../../src/context/virtual-drive/folders/domain/file-systems/LocalFileSystem'; +import { LocalFolderSystem } from '../../../../../src/context/virtual-drive/folders/domain/file-systems/LocalFolderSystem'; -export class FolderLocalFileSystemMock implements LocalFileSystem { +export class FolderLocalFileSystemMock implements LocalFolderSystem { public readonly createPlaceHolderMock = jest.fn(); public readonly getLocalFolderIdMock = jest.fn(); public readonly updateSyncStatusMock = jest.fn(); From 67cb45e3b301e20e6a96e87981afec3973e616d8 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Tue, 3 Sep 2024 13:28:34 -0300 Subject: [PATCH 06/18] fix some smell issues --- src/apps/shared/HttpClient/HttpClient.ts | 7 +++++-- src/apps/sync-engine/BindingManager.ts | 13 +------------ .../dependency-injection/common/QueueManager.ts | 3 +++ .../application/FileSyncOrchestrator.ts | 12 ++++++++---- .../files/application/FilesPlaceholderUpdater.ts | 2 -- .../files/domain/file-systems/LocalFileSystem.ts | 2 +- .../folders/application/UpdatePlaceholderFolder.ts | 2 -- 7 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/apps/shared/HttpClient/HttpClient.ts b/src/apps/shared/HttpClient/HttpClient.ts index a422e9310..2d7f67d5f 100644 --- a/src/apps/shared/HttpClient/HttpClient.ts +++ b/src/apps/shared/HttpClient/HttpClient.ts @@ -15,9 +15,12 @@ export class AuthorizedHttpClient { private handleUnauthorizedResponse(error: AxiosError) { if (error?.response?.status === 401) { Logger.warn('[AUTH] Request unauthorized'); - // this.unauthorizedNotifier(); + try { + this.unauthorizedNotifier(); + } catch (error) { + Logger.error('[AUTH] Unauthorized notifier failed', error); + } } - // Prevent the token from being displayed in the logs if (error.config.headers?.Authorization) { error.config.headers['Authorization'] = 'Bearer ****************'; diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index c874847ea..b47a52d53 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -303,18 +303,7 @@ export class BindingsManager { const callbacks = { handleAdd: async (task: QueueItem) => { try { - Logger.debug( - 'Path received from callback', - task.path.replace(/\\/g, '/') - ); - - const filePath = new FilePath(task.path.replace(/\\/g, '/')); - - const file = await this.container.fileFinder.findFromFilePath( - filePath - ); - - Logger.debug('File found', file); + Logger.debug('Path received from handle add', task.path); const itemId = await this.controllers.addFile.execute(task.path); if (!itemId) { diff --git a/src/apps/sync-engine/dependency-injection/common/QueueManager.ts b/src/apps/sync-engine/dependency-injection/common/QueueManager.ts index fd9e0c8a3..ce803b5cc 100644 --- a/src/apps/sync-engine/dependency-injection/common/QueueManager.ts +++ b/src/apps/sync-engine/dependency-injection/common/QueueManager.ts @@ -91,6 +91,9 @@ export class QueueManager implements IQueueManager { } const data = fs.readFileSync(this.persistPath, 'utf-8'); + if (!data) { + return; + } this.queues = JSON.parse(data); } } diff --git a/src/context/virtual-drive/boundaryBridge/application/FileSyncOrchestrator.ts b/src/context/virtual-drive/boundaryBridge/application/FileSyncOrchestrator.ts index d6f342379..7d09a9e40 100644 --- a/src/context/virtual-drive/boundaryBridge/application/FileSyncOrchestrator.ts +++ b/src/context/virtual-drive/boundaryBridge/application/FileSyncOrchestrator.ts @@ -9,10 +9,14 @@ export class FileSyncOrchestrator { async run(absolutePaths: string[]): Promise { for (const absolutePath of absolutePaths) { - await this.fileSyncronizer.run( - absolutePath, - this.contentsUploader.run.bind(this.contentsUploader) - ); + try { + await this.fileSyncronizer.run( + absolutePath, + this.contentsUploader.run.bind(this.contentsUploader) + ); + } catch (error) { + console.error(error); + } } } } diff --git a/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts b/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts index aac016a3a..3e672c5e6 100644 --- a/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts +++ b/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts @@ -77,8 +77,6 @@ export class FilesPlaceholderUpdater { ); await fs.unlink(win32AbsolutePath); } - - await this.localFileSystem.updateSyncStatus(remote, false); } async run(remotes: Array): Promise { diff --git a/src/context/virtual-drive/files/domain/file-systems/LocalFileSystem.ts b/src/context/virtual-drive/files/domain/file-systems/LocalFileSystem.ts index 4b03c3de3..5090349a2 100644 --- a/src/context/virtual-drive/files/domain/file-systems/LocalFileSystem.ts +++ b/src/context/virtual-drive/files/domain/file-systems/LocalFileSystem.ts @@ -8,7 +8,7 @@ export interface LocalFileSystem { getLocalFileId(file: File): Promise<`${string}-${string}`>; - updateSyncStatus(file: File, status: boolean): Promise; + updateSyncStatus(file: File): Promise; getFileIdentity(path: File['path']): Promise; diff --git a/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts b/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts index 78617c8b4..3426b026d 100644 --- a/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts +++ b/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts @@ -135,8 +135,6 @@ export class FolderPlaceholderUpdater { await fs.rm(win32AbsolutePath, { recursive: true }); return; } - - await this.local.updateSyncStatus(remote, false); } async run(remotes: Array): Promise { From 3dfd35f1e31d3f4a90bf7537878778912b919717 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 4 Sep 2024 13:50:23 -0300 Subject: [PATCH 07/18] Implemented the changes for ticket PB-2692. Integrated the new endpoint to retrieve folder metadata during creation. This update ensures that when a folder is created, the correct metadata is fetched and stored, addressing the issues related to folder persistence and synchronization. --- src/apps/main/auth/handlers.ts | 4 +- src/apps/main/auth/refresh-token.ts | 39 +++++++++++++++- src/apps/main/auth/service.ts | 7 +-- src/apps/main/preload.d.ts | 7 +++ src/apps/main/preload.js | 7 +++ .../main/remote-sync/RemoteSyncManager.ts | 4 +- src/apps/main/types.ts | 1 + .../dependency-injection/common/traverser.ts | 3 +- .../dependency-injection/folders/builder.ts | 14 +++--- .../dependency-injection/items/builder.ts | 6 ++- src/context/shared/domain/ServerFolder.ts | 1 + .../folders/application/FolderCreator.ts | 4 +- .../folders/application/FolderDeleter.ts | 2 +- .../folders/application/FolderMover.ts | 2 +- .../application/FolderPlaceholderDeleter.ts | 2 +- .../folders/application/FolderRenamer.ts | 2 +- .../Offline/OfflineFolderCreator.ts | 7 ++- .../folders/domain/OfflineFolder.ts | 19 +++++++- ...oteFileSystem.ts => RemoteFolderSystem.ts} | 2 +- ...ileSystem.ts => HttpRemoteFolderSystem.ts} | 44 ++++++++++++++++++- .../items/application/Traverser.ts | 14 +++--- .../__mocks__/FolderRemoteFileSystemMock.ts | 2 +- 22 files changed, 157 insertions(+), 36 deletions(-) rename src/context/virtual-drive/folders/domain/file-systems/{RemoteFileSystem.ts => RemoteFolderSystem.ts} (91%) rename src/context/virtual-drive/folders/infrastructure/{HttpRemoteFileSystem.ts => HttpRemoteFolderSystem.ts} (72%) diff --git a/src/apps/main/auth/handlers.ts b/src/apps/main/auth/handlers.ts index 077d18da3..ff0570ab6 100644 --- a/src/apps/main/auth/handlers.ts +++ b/src/apps/main/auth/handlers.ts @@ -6,7 +6,7 @@ import { applicationOpened } from '../analytics/service'; import eventBus from '../event-bus'; import { setupRootFolder } from '../virtual-root-folder/service'; import { getWidget } from '../windows/widget'; -import { createTokenSchedule } from './refresh-token'; +import { checkUserData, createTokenSchedule } from './refresh-token'; import { canHisConfigBeRestored, encryptToken, @@ -79,7 +79,7 @@ eventBus.on('APP_IS_READY', async () => { if (!isLoggedIn) { return; } - + await checkUserData(); encryptToken(); applicationOpened(); await createTokenSchedule(); diff --git a/src/apps/main/auth/refresh-token.ts b/src/apps/main/auth/refresh-token.ts index 50a94a251..8099ee2a6 100644 --- a/src/apps/main/auth/refresh-token.ts +++ b/src/apps/main/auth/refresh-token.ts @@ -1,14 +1,21 @@ import Logger from 'electron-log'; -import { getClient } from '../../shared/HttpClient/main-process-client'; +import { + getClient, + getNewTokenClient, +} from '../../shared/HttpClient/main-process-client'; import { TokenScheduler } from '../token-scheduler/TokenScheduler'; import { onUserUnauthorized } from './handlers'; import { + getUser, obtainTokens as obtainStoredTokens, + setUser, updateCredentials, } from './service'; +import axios from 'axios'; const authorizedClient = getClient(); +const newAuthorizedClient = getNewTokenClient(); async function obtainTokens() { try { @@ -48,3 +55,33 @@ export async function createTokenSchedule(refreshedTokens?: Array) { createTokenSchedule(await refreshToken()); } } + +async function getRootFolderMetadata(rootFolderid: number) { + try { + const res = await newAuthorizedClient.get( + `${process.env.NEW_DRIVE_URL}/drive/folders/${rootFolderid}/metadata` + ); + + Logger.info('[AUTH] Got root folder metadata', res.data); + return res.data; + } catch (err) { + Logger.error('[AUTH] Could not get root folder metadata', err); + if (axios.isAxiosError(err)) { + Logger.error('[Is Axios Error]', err.response?.data); + } + return null; + } +} + +export async function checkUserData(): Promise { + const user = getUser(); + if (user?.root_folder_id && !user?.rootFolderId) { + const rootFolderMetadata = await getRootFolderMetadata(user.root_folder_id); + if (rootFolderMetadata) { + setUser({ + ...user, + rootFolderId: rootFolderMetadata.uuid, + }); + } + } +} diff --git a/src/apps/main/auth/service.ts b/src/apps/main/auth/service.ts index fb56ce325..167d2b3ee 100644 --- a/src/apps/main/auth/service.ts +++ b/src/apps/main/auth/service.ts @@ -86,6 +86,10 @@ export function setCredentials( ConfigStore.set('newTokenEncrypted', isSafeStorageAvailable); } +export function setUser(userData: User) { + ConfigStore.set('userData', userData); +} + export function updateCredentials( bearerToken: string, newBearerToken?: string @@ -146,7 +150,6 @@ export function getUser(): User | null { return user && Object.keys(user).length ? user : null; } - export function obtainTokens(): Array { return tokensKeys.map(obtainToken); } @@ -220,5 +223,3 @@ export function logout() { resetCredentials(); Logger.info('[AUTH] User logged out'); } - - diff --git a/src/apps/main/preload.d.ts b/src/apps/main/preload.d.ts index 6028d6622..12822ee49 100644 --- a/src/apps/main/preload.d.ts +++ b/src/apps/main/preload.d.ts @@ -11,6 +11,13 @@ declare interface Window { pathChanged(path: string): void; + logger: { + info: (...message: unknown[]) => void; + error: (...message: unknown[]) => void; + warn: (...message: unknown[]) => void; + debug: (...message: unknown[]) => void; + }; + getGeneralIssues: () => Promise< import('../../apps/shared/types').GeneralIssue[] >; diff --git a/src/apps/main/preload.js b/src/apps/main/preload.js index fce37a19c..1115029fc 100644 --- a/src/apps/main/preload.js +++ b/src/apps/main/preload.js @@ -1,5 +1,6 @@ const { contextBridge, ipcRenderer } = require('electron'); const path = require('path'); +const Logger = require('electron-log'); contextBridge.exposeInMainWorld('electron', { getConfigKey(key) { @@ -16,6 +17,12 @@ contextBridge.exposeInMainWorld('electron', { return () => ipcRenderer.removeListener(eventName, callback); }, + logger: { + info: (...message) => Logger.info(message), + error: (...message) => Logger.error(message), + warn: (...message) => Logger.warn(message), + }, + pathChanged(pathname) { ipcRenderer.send('path-changed', pathname); }, diff --git a/src/apps/main/remote-sync/RemoteSyncManager.ts b/src/apps/main/remote-sync/RemoteSyncManager.ts index cb130787c..7daf24b41 100644 --- a/src/apps/main/remote-sync/RemoteSyncManager.ts +++ b/src/apps/main/remote-sync/RemoteSyncManager.ts @@ -676,7 +676,7 @@ export class RemoteSyncManager { ); Logger.info( `Fetching item ${type} response: ${JSON.stringify( - response.data[0], + response.data?.length, null, 2 )}` @@ -700,7 +700,7 @@ export class RemoteSyncManager { ); Logger.info( `Fetching by folder ${type} by folder response: ${JSON.stringify( - response.data.result[0], + response.data.result?.length, null, 2 )}` diff --git a/src/apps/main/types.ts b/src/apps/main/types.ts index cab195049..8e06531c9 100644 --- a/src/apps/main/types.ts +++ b/src/apps/main/types.ts @@ -14,6 +14,7 @@ export type User = { registerCompleted: boolean; revocateKey: string; root_folder_id: number; + rootFolderId: string; sharedWorkspace: boolean; teams: boolean; userId: string; diff --git a/src/apps/sync-engine/dependency-injection/common/traverser.ts b/src/apps/sync-engine/dependency-injection/common/traverser.ts index be17a4e0c..f7b3017df 100644 --- a/src/apps/sync-engine/dependency-injection/common/traverser.ts +++ b/src/apps/sync-engine/dependency-injection/common/traverser.ts @@ -16,7 +16,8 @@ export class DependencyInjectionTraverserProvider { const traverser = Traverser.existingItems( crypt, ipcRendererSyncEngine, - user.root_folder_id + user.root_folder_id, + user.rootFolderId ); DependencyInjectionTraverserProvider.traverser = traverser; diff --git a/src/apps/sync-engine/dependency-injection/folders/builder.ts b/src/apps/sync-engine/dependency-injection/folders/builder.ts index f3cc0c4ee..7d7cbb933 100644 --- a/src/apps/sync-engine/dependency-injection/folders/builder.ts +++ b/src/apps/sync-engine/dependency-injection/folders/builder.ts @@ -17,7 +17,7 @@ import { RetrieveAllFolders } from '../../../../context/virtual-drive/folders/ap import { SynchronizeOfflineModifications } from '../../../../context/virtual-drive/folders/application/SynchronizeOfflineModifications'; import { SynchronizeOfflineModificationsOnFolderCreated } from '../../../../context/virtual-drive/folders/application/SynchronizeOfflineModificationsOnFolderCreated'; import { FolderPlaceholderUpdater } from '../../../../context/virtual-drive/folders/application/UpdatePlaceholderFolder'; -import { HttpRemoteFileSystem } from '../../../../context/virtual-drive/folders/infrastructure/HttpRemoteFileSystem'; +import { HttpRemoteFolderSystem } from '../../../../context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem'; import { InMemoryFolderRepository } from '../../../../context/virtual-drive/folders/infrastructure/InMemoryFolderRepository'; import { InMemoryOfflineFolderRepository } from '../../../../context/virtual-drive/folders/infrastructure/InMemoryOfflineFolderRepository'; import { ipcRendererSyncEngine } from '../../ipcRendererSyncEngine'; @@ -48,7 +48,7 @@ export async function buildFoldersContainer( virtualDrive, shredContainer.relativePathToAbsoluteConverter ); - const remoteFileSystem = new HttpRemoteFileSystem( + const remoteFolderSystem = new HttpRemoteFolderSystem( clients.drive, clients.newDrive ); @@ -67,7 +67,7 @@ export async function buildFoldersContainer( const folderDeleter = new FolderDeleter( repository, - remoteFileSystem, + remoteFolderSystem, localFileSystem, allParentFoldersStatusIsExists ); @@ -76,7 +76,7 @@ export async function buildFoldersContainer( const folderCreator = new FolderCreator( repository, - remoteFileSystem, + remoteFolderSystem, ipcRendererSyncEngine, eventBus, folderPlaceholderConverter @@ -84,12 +84,12 @@ export async function buildFoldersContainer( const folderMover = new FolderMover( repository, - remoteFileSystem, + remoteFolderSystem, folderFinder ); const folderRenamer = new FolderRenamer( repository, - remoteFileSystem, + remoteFolderSystem, ipcRendererSyncEngine ); @@ -144,7 +144,7 @@ export async function buildFoldersContainer( const folderPlaceholderDeleter = new FolderPlaceholderDeleter( shredContainer.relativePathToAbsoluteConverter, - remoteFileSystem, + remoteFolderSystem, localFileSystem ); diff --git a/src/apps/sync-engine/dependency-injection/items/builder.ts b/src/apps/sync-engine/dependency-injection/items/builder.ts index 20a7c7ffd..7be801d59 100644 --- a/src/apps/sync-engine/dependency-injection/items/builder.ts +++ b/src/apps/sync-engine/dependency-injection/items/builder.ts @@ -20,12 +20,14 @@ export function buildItemsContainer(): ItemsContainer { const existingItemsTraverser = Traverser.existingItems( nameDecryptor, ipcRendererSyncEngine, - user.root_folder_id + user.root_folder_id, + user.rootFolderId ); const allStatusesTraverser = Traverser.allItems( nameDecryptor, ipcRendererSyncEngine, - user.root_folder_id + user.root_folder_id, + user.rootFolderId ); const treeBuilder = new TreeBuilder( remoteItemsGenerator, diff --git a/src/context/shared/domain/ServerFolder.ts b/src/context/shared/domain/ServerFolder.ts index e1ca1ff35..7af7e6a7d 100644 --- a/src/context/shared/domain/ServerFolder.ts +++ b/src/context/shared/domain/ServerFolder.ts @@ -15,4 +15,5 @@ export type ServerFolder = { plain_name: string | null; status: ServerFolderStatus; uuid: string; + removed: boolean; }; diff --git a/src/context/virtual-drive/folders/application/FolderCreator.ts b/src/context/virtual-drive/folders/application/FolderCreator.ts index 0b64008dc..202a170a4 100644 --- a/src/context/virtual-drive/folders/application/FolderCreator.ts +++ b/src/context/virtual-drive/folders/application/FolderCreator.ts @@ -3,13 +3,13 @@ import { EventBus } from '../../shared/domain/EventBus'; import { Folder } from '../domain/Folder'; import { FolderRepository } from '../domain/FolderRepository'; import { OfflineFolder } from '../domain/OfflineFolder'; -import { RemoteFileSystem } from '../domain/file-systems/RemoteFileSystem'; +import { RemoteFolderSystem } from '../domain/file-systems/RemoteFolderSystem'; import { FolderPlaceholderConverter } from './FolderPlaceholderConverter'; export class FolderCreator { constructor( private readonly repository: FolderRepository, - private readonly remote: RemoteFileSystem, + private readonly remote: RemoteFolderSystem, private readonly ipc: SyncEngineIpc, private readonly eventBus: EventBus, private readonly folderPlaceholderConverter: FolderPlaceholderConverter diff --git a/src/context/virtual-drive/folders/application/FolderDeleter.ts b/src/context/virtual-drive/folders/application/FolderDeleter.ts index 2eede9b9e..3293e753a 100644 --- a/src/context/virtual-drive/folders/application/FolderDeleter.ts +++ b/src/context/virtual-drive/folders/application/FolderDeleter.ts @@ -4,7 +4,7 @@ import { ActionNotPermittedError } from '../domain/errors/ActionNotPermittedErro import { FolderNotFoundError } from '../domain/errors/FolderNotFoundError'; import { AllParentFoldersStatusIsExists } from './AllParentFoldersStatusIsExists'; import { FolderRepository } from '../domain/FolderRepository'; -import { RemoteFileSystem } from '../domain/file-systems/RemoteFileSystem'; +import { RemoteFileSystem } from '../domain/file-systems/RemoteFolderSystem'; import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; export class FolderDeleter { diff --git a/src/context/virtual-drive/folders/application/FolderMover.ts b/src/context/virtual-drive/folders/application/FolderMover.ts index f185e9fd8..d0038b70d 100644 --- a/src/context/virtual-drive/folders/application/FolderMover.ts +++ b/src/context/virtual-drive/folders/application/FolderMover.ts @@ -3,7 +3,7 @@ import { FolderPath } from '../domain/FolderPath'; import { Folder } from '../domain/Folder'; import { FolderFinder } from './FolderFinder'; import { FolderRepository } from '../domain/FolderRepository'; -import { RemoteFileSystem } from '../domain/file-systems/RemoteFileSystem'; +import { RemoteFileSystem } from '../domain/file-systems/RemoteFolderSystem'; export class FolderMover { constructor( diff --git a/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts b/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts index 410ffb110..835ec297d 100644 --- a/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts +++ b/src/context/virtual-drive/folders/application/FolderPlaceholderDeleter.ts @@ -1,7 +1,7 @@ import { RelativePathToAbsoluteConverter } from '../../shared/application/RelativePathToAbsoluteConverter'; import { Folder } from '../domain/Folder'; import { FolderStatuses } from '../domain/FolderStatus'; -import { RemoteFileSystem } from '../domain/file-systems/RemoteFileSystem'; +import { RemoteFileSystem } from '../domain/file-systems/RemoteFolderSystem'; import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; import Logger from 'electron-log'; import { sleep } from '../../../../apps/main/util'; diff --git a/src/context/virtual-drive/folders/application/FolderRenamer.ts b/src/context/virtual-drive/folders/application/FolderRenamer.ts index 8304e025c..ea4a198a9 100644 --- a/src/context/virtual-drive/folders/application/FolderRenamer.ts +++ b/src/context/virtual-drive/folders/application/FolderRenamer.ts @@ -1,7 +1,7 @@ import { FolderPath } from '../domain/FolderPath'; import { Folder } from '../domain/Folder'; import { FolderRepository } from '../domain/FolderRepository'; -import { RemoteFileSystem } from '../domain/file-systems/RemoteFileSystem'; +import { RemoteFileSystem } from '../domain/file-systems/RemoteFolderSystem'; import { SyncEngineIpc } from '../../../../apps/sync-engine/ipcRendererSyncEngine'; export class FolderRenamer { diff --git a/src/context/virtual-drive/folders/application/Offline/OfflineFolderCreator.ts b/src/context/virtual-drive/folders/application/Offline/OfflineFolderCreator.ts index 9bd900a35..458dd588a 100644 --- a/src/context/virtual-drive/folders/application/Offline/OfflineFolderCreator.ts +++ b/src/context/virtual-drive/folders/application/Offline/OfflineFolderCreator.ts @@ -1,3 +1,4 @@ +import Logger from 'electron-log'; import { FolderPath } from '../../domain/FolderPath'; import { OfflineFolder } from '../../domain/OfflineFolder'; import { OfflineFolderRepository } from '../../domain/OfflineFolderRepository'; @@ -26,7 +27,11 @@ export class OfflineFolderCreator { const parent = this.folderFinder.run(folderPath.dirname()); - const folder = OfflineFolder.create(folderPath, parent.id); + Logger.debug('[DEBUG IN OFFLINEFOLDERCREATOR STEEP 1]'); + + Logger.debug(parent); + + const folder = OfflineFolder.create(folderPath, parent.id, parent.uuid); this.offlineRepository.update(folder); diff --git a/src/context/virtual-drive/folders/domain/OfflineFolder.ts b/src/context/virtual-drive/folders/domain/OfflineFolder.ts index 3d72c4855..d923b794f 100644 --- a/src/context/virtual-drive/folders/domain/OfflineFolder.ts +++ b/src/context/virtual-drive/folders/domain/OfflineFolder.ts @@ -8,6 +8,7 @@ import { FolderRenamedDomainEvent } from './events/FolderRenamedDomainEvent'; export type OfflineFolderAttributes = { uuid: string; parentId: number; + parentUuid: string; path: string; updatedAt: string; createdAt: string; @@ -19,6 +20,7 @@ export class OfflineFolder extends AggregateRoot { private _uuid: FolderUuid, private _path: FolderPath, private _parentId: number, + private _parentUuid: FolderUuid, public createdAt: Date, public updatedAt: Date, private _status: FolderStatus @@ -50,6 +52,10 @@ export class OfflineFolder extends AggregateRoot { return this._parentId; } + public get parentUuid() { + return this._parentUuid.value; + } + public get status() { return this._status; } @@ -64,18 +70,27 @@ export class OfflineFolder extends AggregateRoot { new FolderUuid(attributes.uuid), new FolderPath(attributes.path), attributes.parentId, + attributes.parentUuid + ? new FolderUuid(attributes.parentUuid) + : FolderUuid.random(), new Date(attributes.updatedAt), new Date(attributes.createdAt), FolderStatus.fromValue(attributes.status) ); } - static create(path: FolderPath, parentId: number): OfflineFolder { + static create( + path: FolderPath, + parentId: number, + parentUuid: string + ): OfflineFolder { return new OfflineFolder( FolderUuid.random(), path, parentId, + new FolderUuid(parentUuid), new Date(), + new Date(), FolderStatus.Exists ); @@ -83,6 +98,7 @@ export class OfflineFolder extends AggregateRoot { moveTo(destinationFolder: Folder) { this._parentId = destinationFolder.id; + this._parentUuid = new FolderUuid(destinationFolder.uuid); } rename(destination: FolderPath) { @@ -116,6 +132,7 @@ export class OfflineFolder extends AggregateRoot { const attributes: OfflineFolderAttributes = { uuid: this.uuid, parentId: this._parentId, + parentUuid: this._parentUuid.value, path: this._path.value, updatedAt: this.updatedAt.toISOString(), createdAt: this.createdAt.toISOString(), diff --git a/src/context/virtual-drive/folders/domain/file-systems/RemoteFileSystem.ts b/src/context/virtual-drive/folders/domain/file-systems/RemoteFolderSystem.ts similarity index 91% rename from src/context/virtual-drive/folders/domain/file-systems/RemoteFileSystem.ts rename to src/context/virtual-drive/folders/domain/file-systems/RemoteFolderSystem.ts index 613a1d87e..e5cf78417 100644 --- a/src/context/virtual-drive/folders/domain/file-systems/RemoteFileSystem.ts +++ b/src/context/virtual-drive/folders/domain/file-systems/RemoteFolderSystem.ts @@ -2,7 +2,7 @@ import { Folder, FolderAttributes } from '../Folder'; import { FolderStatuses } from '../FolderStatus'; import { OfflineFolder } from '../OfflineFolder'; -export interface RemoteFileSystem { +export interface RemoteFolderSystem { persist(offline: OfflineFolder): Promise; trash(id: Folder['id']): Promise; diff --git a/src/context/virtual-drive/folders/infrastructure/HttpRemoteFileSystem.ts b/src/context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem.ts similarity index 72% rename from src/context/virtual-drive/folders/infrastructure/HttpRemoteFileSystem.ts rename to src/context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem.ts index ece8186c6..1e350c13d 100644 --- a/src/context/virtual-drive/folders/infrastructure/HttpRemoteFileSystem.ts +++ b/src/context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem.ts @@ -4,13 +4,13 @@ import * as uuid from 'uuid'; import { Folder, FolderAttributes } from '../domain/Folder'; import { FolderStatuses } from '../domain/FolderStatus'; import { UpdateFolderNameDTO } from './dtos/UpdateFolderNameDTO'; -import { RemoteFileSystem } from '../domain/file-systems/RemoteFileSystem'; +import { RemoteFolderSystem } from '../domain/file-systems/RemoteFolderSystem'; import { OfflineFolder } from '../domain/OfflineFolder'; import { ServerFolder } from '../../../shared/domain/ServerFolder'; import { CreateFolderDTO } from './dtos/CreateFolderDTO'; import * as Sentry from '@sentry/electron/renderer'; -export class HttpRemoteFileSystem implements RemoteFileSystem { +export class HttpRemoteFolderSystem implements RemoteFolderSystem { public folders: Record = {}; constructor( @@ -57,7 +57,47 @@ export class HttpRemoteFileSystem implements RemoteFileSystem { Sentry.captureException(error); if (axios.isAxiosError(error)) { Logger.error('[Is Axios Error]', error.response?.data); + const existing = await this.existFolder(offline); + return existing.status !== FolderStatuses.EXISTS + ? Promise.reject(error) + : existing; } + + throw error; + } + } + + private async existFolder(offline: OfflineFolder): Promise { + try { + const response = await this.trashClient.get( + `${process.env.NEW_DRIVE_URL}/drive/folders/content/${offline.parentUuid}/folders/existence?plainName=${offline.basename}` + ); + Logger.debug('[FOLDER FILE SYSTEM] Folder already exists', response.data); + + const serverFolder = response.data + .existentFolders[0] as ServerFolder | null; + + if (!serverFolder) { + throw new Error('Folder creation failed, no data returned'); + } + return { + id: serverFolder.id, + uuid: serverFolder.uuid, + parentId: serverFolder.parentId, + updatedAt: serverFolder.updatedAt, + createdAt: serverFolder.createdAt, + path: offline.path.value, + status: serverFolder.removed + ? FolderStatuses.TRASHED + : FolderStatuses.EXISTS, + }; + } catch (error) { + Logger.error('[FOLDER FILE SYSTEM] Error creating folder'); + Sentry.captureException(error); + if (axios.isAxiosError(error)) { + Logger.error('[Is Axios Error]', error.response?.data); + } + throw error; } } diff --git a/src/context/virtual-drive/items/application/Traverser.ts b/src/context/virtual-drive/items/application/Traverser.ts index f8beb3a00..f06927eda 100644 --- a/src/context/virtual-drive/items/application/Traverser.ts +++ b/src/context/virtual-drive/items/application/Traverser.ts @@ -29,6 +29,7 @@ export class Traverser { private readonly decrypt: NameDecrypt, private readonly ipc: SyncEngineIpc, private readonly baseFolderId: number, + private readonly baseFolderUuid: string, private fileStatusesToFilter: Array, private folderStatusesToFilter: Array ) {} @@ -36,12 +37,14 @@ export class Traverser { static existingItems( decrypt: NameDecrypt, ipc: SyncEngineIpc, - baseFolderId: number + baseFolderId: number, + baseFolderUuid: string ): Traverser { return new Traverser( decrypt, ipc, baseFolderId, + baseFolderUuid, [ServerFileStatus.EXISTS], [ServerFolderStatus.EXISTS] ); @@ -50,9 +53,10 @@ export class Traverser { static allItems( decrypt: NameDecrypt, ipc: SyncEngineIpc, - baseFolderId: number + baseFolderId: number, + baseFolderUuid: string ): Traverser { - return new Traverser(decrypt, ipc, baseFolderId, [], []); + return new Traverser(decrypt, ipc, baseFolderId, baseFolderUuid, [], []); } public setFileStatusesToFilter(statuses: Array): void { @@ -64,11 +68,9 @@ export class Traverser { } private createRootFolder(): Folder { - const rootFolderUuid = '43711926-15c2-5ebf-8c24-5099fa9af3c3'; - return Folder.from({ id: this.baseFolderId, - uuid: rootFolderUuid, + uuid: this.baseFolderUuid, parentId: null, updatedAt: new Date().toISOString(), createdAt: new Date().toISOString(), diff --git a/tests/context/virtual-drive/folders/__mocks__/FolderRemoteFileSystemMock.ts b/tests/context/virtual-drive/folders/__mocks__/FolderRemoteFileSystemMock.ts index 4a43211c3..0549e6b1a 100644 --- a/tests/context/virtual-drive/folders/__mocks__/FolderRemoteFileSystemMock.ts +++ b/tests/context/virtual-drive/folders/__mocks__/FolderRemoteFileSystemMock.ts @@ -3,7 +3,7 @@ import { FolderAttributes, } from '../../../../../src/context/virtual-drive/folders/domain/Folder'; import { OfflineFolder } from '../../../../../src/context/virtual-drive/folders/domain/OfflineFolder'; -import { RemoteFileSystem } from '../../../../../src/context/virtual-drive/folders/domain/file-systems/RemoteFileSystem'; +import { RemoteFileSystem } from '../../../../../src/context/virtual-drive/folders/domain/file-systems/RemoteFolderSystem'; export class FolderRemoteFileSystemMock implements RemoteFileSystem { public readonly persistMock = jest.fn(); From 7609c84444bd0d05b0579d1aa470bb88321601f4 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 4 Sep 2024 13:51:27 -0300 Subject: [PATCH 08/18] update package json --- package.json | 2 +- release/app/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index bad57b139..a571159f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.1", + "version": "2.1.2-qa", "author": "Internxt ", "description": "Internxt Drive client UI", "license": "AGPL-3.0", diff --git a/release/app/package.json b/release/app/package.json index 2afbcc492..99a4d10b1 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.1", + "version": "2.1.2-qa", "description": "Internxt Drive client UI", "main": "./dist/main/main.js", "author": "Internxt ", From 50aa25546de705f5e6de6ba98217453196f66802 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Fri, 6 Sep 2024 13:38:13 -0300 Subject: [PATCH 09/18] Worked on a fix for the download process, resolved the refresh token error, and fixed the logout bug. --- src/apps/main/auth/handlers.ts | 1 + src/apps/main/auth/refresh-token.ts | 12 ++--- .../main/background-processes/sync-engine.ts | 4 ++ src/apps/main/main.ts | 1 - src/apps/main/remote-sync/handlers.ts | 1 + src/apps/main/virtual-root-folder/service.ts | 34 ++++++++------ .../shared/HttpClient/main-process-client.ts | 4 +- src/apps/sync-engine/BindingManager.ts | 17 +++++-- src/apps/sync-engine/index.ts | 8 ++++ .../application/ContentsDownloader.ts | 8 ---- .../NotifyMainProcessHydrationFinished.ts | 47 ++++++++++++------- 11 files changed, 87 insertions(+), 50 deletions(-) diff --git a/src/apps/main/auth/handlers.ts b/src/apps/main/auth/handlers.ts index ff0570ab6..323b19cd2 100644 --- a/src/apps/main/auth/handlers.ts +++ b/src/apps/main/auth/handlers.ts @@ -49,6 +49,7 @@ ipcMain.handle('get-token', () => { export function onUserUnauthorized() { eventBus.emit('USER_WAS_UNAUTHORIZED'); + eventBus.emit('USER_LOGGED_OUT'); logout(); Logger.info('[AUTH] User has been logged out because it was unauthorized'); diff --git a/src/apps/main/auth/refresh-token.ts b/src/apps/main/auth/refresh-token.ts index 8099ee2a6..880d38045 100644 --- a/src/apps/main/auth/refresh-token.ts +++ b/src/apps/main/auth/refresh-token.ts @@ -1,9 +1,6 @@ import Logger from 'electron-log'; -import { - getClient, - getNewTokenClient, -} from '../../shared/HttpClient/main-process-client'; +import { getNewTokenClient } from '../../shared/HttpClient/main-process-client'; import { TokenScheduler } from '../token-scheduler/TokenScheduler'; import { onUserUnauthorized } from './handlers'; import { @@ -14,14 +11,13 @@ import { } from './service'; import axios from 'axios'; -const authorizedClient = getClient(); const newAuthorizedClient = getNewTokenClient(); async function obtainTokens() { try { Logger.debug('[TOKEN] Obtaining new tokens'); - const res = await authorizedClient.get( - `${process.env.API_URL}/user/refresh` + const res = await newAuthorizedClient.get( + `${process.env.NEW_DRIVE_URL}/drive/users/refresh` ); return res.data; @@ -41,6 +37,7 @@ async function refreshToken() { updateCredentials(token, newToken); + Logger.debug('[TOKEN] Refreshed tokens', token, newToken); return [token, newToken]; } @@ -83,5 +80,6 @@ export async function checkUserData(): Promise { rootFolderId: rootFolderMetadata.uuid, }); } + refreshToken(); } } diff --git a/src/apps/main/background-processes/sync-engine.ts b/src/apps/main/background-processes/sync-engine.ts index 358e47ca6..0fab779af 100644 --- a/src/apps/main/background-processes/sync-engine.ts +++ b/src/apps/main/background-processes/sync-engine.ts @@ -5,6 +5,7 @@ import eventBus from '../event-bus'; import nodeSchedule from 'node-schedule'; import * as Sentry from '@sentry/electron/main'; import { checkSyncEngineInProcess } from '../remote-sync/handlers'; +import { clearRootVirtualDrive } from '../virtual-root-folder/service'; let worker: BrowserWindow | null = null; let workerIsRunning = false; @@ -188,6 +189,8 @@ async function stopAndClearSyncEngineWatcher() { Logger.info('[MAIN] WORKER WAS NOT RUNNING'); worker?.destroy(); worker = null; + await clearRootVirtualDrive(); + return; } @@ -229,6 +232,7 @@ async function stopAndClearSyncEngineWatcher() { worker?.destroy(); workerIsRunning = false; worker = null; + await clearRootVirtualDrive(); } } diff --git a/src/apps/main/main.ts b/src/apps/main/main.ts index 2cafa8338..fd8e140a7 100644 --- a/src/apps/main/main.ts +++ b/src/apps/main/main.ts @@ -121,7 +121,6 @@ eventBus.on('USER_LOGGED_IN', async () => { nativeTheme.themeSource = (configStore.get('preferedTheme') || 'system') as Theme; - setTrayStatus('IDLE'); const widget = await getOrCreateWidged(); const tray = getTray(); if (widget && tray) { diff --git a/src/apps/main/remote-sync/handlers.ts b/src/apps/main/remote-sync/handlers.ts index f9dde2927..fc0a33457 100644 --- a/src/apps/main/remote-sync/handlers.ts +++ b/src/apps/main/remote-sync/handlers.ts @@ -203,6 +203,7 @@ eventBus.on('USER_LOGGED_IN', async () => { Logger.info('Received user logged in event'); try { remoteSyncManager.isProcessRunning = true; + setTrayStatus('SYNCING'); const userData = configStore.get('userData'); const lastFilesSyncAt = await remoteSyncManager.getFileCheckpoint(); Logger.info('Last files sync at', lastFilesSyncAt); diff --git a/src/apps/main/virtual-root-folder/service.ts b/src/apps/main/virtual-root-folder/service.ts index 298abf591..c4bcd8399 100644 --- a/src/apps/main/virtual-root-folder/service.ts +++ b/src/apps/main/virtual-root-folder/service.ts @@ -1,3 +1,4 @@ +import Logger from 'electron-log'; import { app, dialog, shell } from 'electron'; import fs from 'fs/promises'; import path from 'path'; @@ -76,26 +77,31 @@ export function getRootVirtualDrive(): string { return configStore.get('syncRoot'); } -export async function setupRootFolder(n = 0): Promise { - setSyncRoot(VIRTUAL_DRIVE_FOLDER); - return; - const folderName = ROOT_FOLDER_NAME; +export async function clearRootVirtualDrive(): Promise { + try { + const syncFolderPath = getRootVirtualDrive(); + + const queue = path.join( + app.getPath('appData'), + 'internxt-drive', + 'queue-manager.json' + ); - const rootFolderName = folderName + (n ? ` (${n})` : ''); - const rootFolderPath = path.join(HOME_FOLDER_PATH, rootFolderName); + await fs.rm(queue, { recursive: true, force: true }); - const notExistsOrIsEmpty = - !(await existsFolder(rootFolderPath)) || - (await isEmptyFolder(rootFolderPath)); + await fs.rm(syncFolderPath, { recursive: true, force: true }); - if (notExistsOrIsEmpty) { - await fs.mkdir(rootFolderPath, { recursive: true }); - setSyncRoot(rootFolderPath); - } else { - return setupRootFolder(n + 1); + Logger.info(`Directory contents cleared: ${syncFolderPath}`); + } catch (err) { + Logger.error('Error clearing root virtual drive', err); } } +export async function setupRootFolder(n = 0): Promise { + setSyncRoot(VIRTUAL_DRIVE_FOLDER); + return; +} + export async function chooseSyncRootWithDialog(): Promise { const result = await dialog.showOpenDialog({ properties: ['openDirectory'] }); if (!result.canceled) { diff --git a/src/apps/shared/HttpClient/main-process-client.ts b/src/apps/shared/HttpClient/main-process-client.ts index cc07d288d..09d1a823e 100644 --- a/src/apps/shared/HttpClient/main-process-client.ts +++ b/src/apps/shared/HttpClient/main-process-client.ts @@ -1,9 +1,11 @@ import { Axios } from 'axios'; -import { onUserUnauthorized } from '../../main/auth/handlers'; import { getHeaders, getNewApiHeaders } from '../../main/auth/service'; import { AuthorizedClients } from './Clients'; import { AuthorizedHttpClient } from './HttpClient'; +import { ipcMain } from 'electron'; + +const onUserUnauthorized = () => ipcMain.emit('user-is-unauthorized'); const headersProvider = () => Promise.resolve(getHeaders(false)); const newHeadersProvider = () => Promise.resolve(getNewApiHeaders()); diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index b47a52d53..43d330d18 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -136,6 +136,7 @@ export class BindingsManager { ) => { try { Logger.debug('[Fetch Data Callback] Donwloading begins'); + const startTime = Date.now(); const path = await this.controllers.downloadFile.execute( contentsId, callback @@ -184,9 +185,19 @@ export class BindingsManager { }); } this.progressBuffer = 0; - await this.controllers.notifyPlaceholderHydrationFinished.execute( - contentsId - ); + // await this.controllers.notifyPlaceholderHydrationFinished.execute( + // contentsId + // ); + + const finishTime = Date.now(); + + ipcRendererSyncEngine.send('FILE_DOWNLOADED', { + name: file.name, + extension: file.type, + nameWithExtension: file.nameWithExtension, + size: file.size, + processInfo: { elapsedTime: finishTime - startTime }, + }); } catch (error) { Logger.error('notify: ', error); Sentry.captureException(error); diff --git a/src/apps/sync-engine/index.ts b/src/apps/sync-engine/index.ts index ab80a7702..99e3f8525 100644 --- a/src/apps/sync-engine/index.ts +++ b/src/apps/sync-engine/index.ts @@ -43,6 +43,14 @@ async function setUp() { icon: iconPath, }); + ipcRenderer.on('USER_LOGGED_OUT', async () => { + bindings.cleanQueue(); + }); + + ipcRenderer.on('CLEAR_QUEUE', async () => { + bindings.cleanQueue(); + }); + ipcRenderer.on('CHECK_SYNC_ENGINE_RESPONSE', async (event) => { Logger.info('[SYNC ENGINE] Checking sync engine response'); const placeholderStatuses = await container.filesCheckerStatusInRoot.run(); diff --git a/src/context/virtual-drive/contents/application/ContentsDownloader.ts b/src/context/virtual-drive/contents/application/ContentsDownloader.ts index f13e2a663..6f204f060 100644 --- a/src/context/virtual-drive/contents/application/ContentsDownloader.ts +++ b/src/context/virtual-drive/contents/application/ContentsDownloader.ts @@ -112,14 +112,6 @@ export class ContentsDownloader { const events = localContents.pullDomainEvents(); await this.eventBus.publish(events); - // this.ipc.send('FILE_DOWNLOADED', { - // name: file.name, - // extension: file.type, - // nameWithExtension: file.nameWithExtension, - // size: file.size, - // processInfo: { elapsedTime: downloader.elapsedTime() }, - // }); - return write; } diff --git a/src/context/virtual-drive/contents/application/NotifyMainProcessHydrationFinished.ts b/src/context/virtual-drive/contents/application/NotifyMainProcessHydrationFinished.ts index faff126b9..01bcd27d7 100644 --- a/src/context/virtual-drive/contents/application/NotifyMainProcessHydrationFinished.ts +++ b/src/context/virtual-drive/contents/application/NotifyMainProcessHydrationFinished.ts @@ -10,25 +10,40 @@ export class NotifyMainProcessHydrationFinished { ) {} async run(contentsId: string) { - const events = await this.eventRepository.search(contentsId); + try { + const events = await this.eventRepository.search(contentsId); - const downloadCompletionEvent = events.find( - (event) => event.eventName === 'contents.downloaded' - ); + const downloadCompletionEvent = events.find( + (event) => event.eventName === 'contents.downloaded' + ); - if (!downloadCompletionEvent) { - Logger.debug('Download completion event not found'); - return; - } + if (!downloadCompletionEvent) { + Logger.debug( + `Download completion event not found for content ID: ${contentsId}` + ); + return; + } - const event = downloadCompletionEvent as ContentsDownloadedDomainEvent; + const event = downloadCompletionEvent as ContentsDownloadedDomainEvent; - this.ipc.send('FILE_DOWNLOADED', { - name: event.name, - extension: event.extension, - nameWithExtension: event.nameWithExtension, - size: event.size, - processInfo: { elapsedTime: event.elapsedTime }, - }); + // Verificar si la conexión sigue activa antes de enviar el mensaje + if (this.ipc) { + this.ipc.send('FILE_DOWNLOADED', { + name: event.name, + extension: event.extension, + nameWithExtension: event.nameWithExtension, + size: event.size, + processInfo: { elapsedTime: event.elapsedTime }, + }); + Logger.info(`Notification sent for file: ${event.nameWithExtension}`); + } else { + Logger.warn('IPC connection is not active or process is not available'); + } + } catch (error) { + Logger.error( + 'Error notifying main process about hydration completion', + error + ); + } } } From 3a4702424ab1c6ce5f72c7dcde02a66608f0e246 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Mon, 9 Sep 2024 09:42:43 -0300 Subject: [PATCH 10/18] fix logout error and update package version --- package.json | 2 +- release/app/package.json | 2 +- src/apps/main/auth/handlers.ts | 6 ++++- src/apps/main/virtual-root-folder/service.ts | 2 +- src/apps/renderer/pages/Widget/Logout.tsx | 6 ++--- src/apps/sync-engine/BindingManager.ts | 26 ++++++++++---------- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index a571159f4..db1f5a3ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.2-qa", + "version": "2.1.2", "author": "Internxt ", "description": "Internxt Drive client UI", "license": "AGPL-3.0", diff --git a/release/app/package.json b/release/app/package.json index 99a4d10b1..1b9c48bd8 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.2-qa", + "version": "2.1.2", "description": "Internxt Drive client UI", "main": "./dist/main/main.js", "author": "Internxt ", diff --git a/src/apps/main/auth/handlers.ts b/src/apps/main/auth/handlers.ts index 323b19cd2..fc6b49d0d 100644 --- a/src/apps/main/auth/handlers.ts +++ b/src/apps/main/auth/handlers.ts @@ -4,7 +4,10 @@ import Logger from 'electron-log'; import { AccessResponse } from '../../renderer/pages/Login/service'; import { applicationOpened } from '../analytics/service'; import eventBus from '../event-bus'; -import { setupRootFolder } from '../virtual-root-folder/service'; +import { + clearRootVirtualDrive, + setupRootFolder, +} from '../virtual-root-folder/service'; import { getWidget } from '../windows/widget'; import { checkUserData, createTokenSchedule } from './refresh-token'; import { @@ -63,6 +66,7 @@ ipcMain.on('user-logged-in', async (_, data: AccessResponse) => { if (!canHisConfigBeRestored(data.user.uuid)) { await setupRootFolder(); } + await await clearRootVirtualDrive(); setIsLoggedIn(true); eventBus.emit('USER_LOGGED_IN'); diff --git a/src/apps/main/virtual-root-folder/service.ts b/src/apps/main/virtual-root-folder/service.ts index c4bcd8399..a4ec53def 100644 --- a/src/apps/main/virtual-root-folder/service.ts +++ b/src/apps/main/virtual-root-folder/service.ts @@ -79,7 +79,7 @@ export function getRootVirtualDrive(): string { export async function clearRootVirtualDrive(): Promise { try { - const syncFolderPath = getRootVirtualDrive(); + const syncFolderPath = configStore.get('syncRoot'); const queue = path.join( app.getPath('appData'), diff --git a/src/apps/renderer/pages/Widget/Logout.tsx b/src/apps/renderer/pages/Widget/Logout.tsx index 561cadd96..d8cffbe99 100644 --- a/src/apps/renderer/pages/Widget/Logout.tsx +++ b/src/apps/renderer/pages/Widget/Logout.tsx @@ -35,10 +35,8 @@ const ModalLogout: React.FC = ({ return syncPending || wasSyncing || existFileUnsync.length > 0; }; - window.electron.updateUnsycFileInSyncEngine().then(() => { - checkSyncPending().then((value) => { - setIsSyncPending(value); - }); + checkSyncPending().then((value) => { + setIsSyncPending(value); }); }, [syncStatus]); diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index 43d330d18..c98480b18 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -424,24 +424,24 @@ export class BindingsManager { async cleanUp() { await VirtualDrive.unregisterSyncRoot(this.paths.root); - const files = await this.container.retrieveAllFiles.run(); - const folders = await this.container.retrieveAllFolders.run(); + // const files = await this.container.retrieveAllFiles.run(); + // const folders = await this.container.retrieveAllFolders.run(); - const items = [...files, ...folders]; + // const items = [...files, ...folders]; - const win32AbsolutePaths = items.map((item) => { - const posixRelativePath = item.path; - // este path es relativo al root y en formato posix + // const win32AbsolutePaths = items.map((item) => { + // const posixRelativePath = item.path; + // // este path es relativo al root y en formato posix - const win32RelativePaths = - PlatformPathConverter.posixToWin(posixRelativePath); + // const win32RelativePaths = + // PlatformPathConverter.posixToWin(posixRelativePath); - return this.container.relativePathToAbsoluteConverter.run( - win32RelativePaths - ); - }); + // return this.container.relativePathToAbsoluteConverter.run( + // win32RelativePaths + // ); + // }); - Logger.debug('win32AbsolutePaths', win32AbsolutePaths); + // Logger.debug('win32AbsolutePaths', win32AbsolutePaths); // find all common string in remainingItems and win32AbsolutePaths // and delete them From e62d1611c5516f9812150f39c910c3b958c8b636 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 11 Sep 2024 16:59:39 -0300 Subject: [PATCH 11/18] Added validations to prevent temporary files in the app --- src/apps/sync-engine/BindingManager.ts | 25 +++++++++++-- src/apps/utils/isTemporalFile.ts | 36 +++++++++++++++++++ .../application/FileSyncOrchestrator.ts | 10 ++++++ 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/apps/utils/isTemporalFile.ts diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index c98480b18..ae7fb65c6 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -2,7 +2,6 @@ import Logger from 'electron-log'; import * as fs from 'fs'; import { VirtualDrive, QueueItem } from 'virtual-drive/dist'; import { FilePlaceholderId } from '../../context/virtual-drive/files/domain/PlaceholderId'; -import { PlatformPathConverter } from '../../context/virtual-drive/shared/application/PlatformPathConverter'; import { IControllers, buildControllers, @@ -20,6 +19,7 @@ import { QueueManager } from './dependency-injection/common/QueueManager'; import { DependencyInjectionLogWatcherPath } from './dependency-injection/common/logEnginePath'; import configStore from '../main/config'; import { FilePath } from '../../context/virtual-drive/files/domain/FilePath'; +import { isTemporaryFile } from '../utils/isTemporalFile'; export type CallbackDownload = ( success: boolean, @@ -93,12 +93,12 @@ export class BindingsManager { Sentry.captureException(error); callback(false); }); - ipcRenderer.send('CHECK_SYNC'); + ipcRenderer.send('SYNCED'); }, notifyDeleteCompletionCallback: () => { Logger.info('Deletion completed'); }, - notifyRenameCallback: ( + notifyRenameCallback: async ( absolutePath: string, contentsId: string, callback: (response: boolean) => void @@ -106,6 +106,16 @@ export class BindingsManager { try { Logger.debug('Path received from rename callback', absolutePath); + const isTempFile = await isTemporaryFile(absolutePath); + + Logger.debug('[isTemporaryFile]', isTempFile); + + if (isTempFile) { + Logger.debug('File is temporary, skipping'); + callback(true); + return; + } + const fn = executeControllerWithFallback({ handler: this.controllers.renameOrMove.execute.bind( this.controllers.renameOrMove @@ -316,6 +326,15 @@ export class BindingsManager { try { Logger.debug('Path received from handle add', task.path); + const tempFile = await isTemporaryFile(task.path); + + Logger.debug('[isTemporaryFile]', tempFile); + + if (tempFile) { + Logger.debug('File is temporary, skipping'); + return; + } + const itemId = await this.controllers.addFile.execute(task.path); if (!itemId) { Logger.error('Error adding file' + task.path); diff --git a/src/apps/utils/isTemporalFile.ts b/src/apps/utils/isTemporalFile.ts new file mode 100644 index 000000000..b8e0976fb --- /dev/null +++ b/src/apps/utils/isTemporalFile.ts @@ -0,0 +1,36 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import Logger from 'electron-log'; + +// Function to check if the file is marked as temporary by the OS (Windows example) +export const isTemporaryFile = async (filePath: string): Promise => { + try { + // Check if the file name starts with a common temporary prefix + if (path.basename(filePath).startsWith('~$')) { + return true; + } + + // // Check if the file has common temporary file extensions + const tempExtensions = ['.tmp', '.temp', '.swp']; + if (tempExtensions.includes(path.extname(filePath).toLowerCase())) { + return true; + } + + // check if havent extension + if (!path.extname(filePath)) { + Logger.debug(`File ${filePath} has no extension`); + return true; + } + + // Check if the file has the "TEMPORARY" attribute (Windows-specific) + // const stats = await fs.promises.stat(filePath); + // if (stats.isFile()) { + // return stats.mode !== 0; + // } + + return false; + } catch (error) { + Logger.error(`Failed to check if the file is temporary: ${error}`); + return false; + } +}; diff --git a/src/context/virtual-drive/boundaryBridge/application/FileSyncOrchestrator.ts b/src/context/virtual-drive/boundaryBridge/application/FileSyncOrchestrator.ts index 7d09a9e40..5d13b31cc 100644 --- a/src/context/virtual-drive/boundaryBridge/application/FileSyncOrchestrator.ts +++ b/src/context/virtual-drive/boundaryBridge/application/FileSyncOrchestrator.ts @@ -1,5 +1,7 @@ +import { isTemporaryFile } from '../../../../apps/utils/isTemporalFile'; import { RetryContentsUploader } from '../../contents/application/RetryContentsUploader'; import { FileSyncronizer } from '../../files/application/FileSyncronizer'; +import Logger from 'electron-log'; export class FileSyncOrchestrator { constructor( @@ -9,6 +11,14 @@ export class FileSyncOrchestrator { async run(absolutePaths: string[]): Promise { for (const absolutePath of absolutePaths) { + const tempFile = await isTemporaryFile(absolutePath); + + Logger.debug('[isTemporaryFile]', tempFile); + + if (tempFile) { + Logger.debug(`Skipping temporary file: ${absolutePath}`); + continue; + } try { await this.fileSyncronizer.run( absolutePath, From 52a26b3264654a006b41ef9fb14c4f04d9d30280 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 18 Sep 2024 11:58:37 -0300 Subject: [PATCH 12/18] update start sync remote start --- .../main/remote-sync/RemoteSyncManager.ts | 1 - src/apps/main/remote-sync/handlers.ts | 11 ++- src/apps/renderer/pages/Widget/index.tsx | 6 +- src/apps/sync-engine/BindingManager.ts | 11 ++- .../infrastructure/FSLocalFileProvider.ts | 92 ++++++++++--------- 5 files changed, 68 insertions(+), 53 deletions(-) diff --git a/src/apps/main/remote-sync/RemoteSyncManager.ts b/src/apps/main/remote-sync/RemoteSyncManager.ts index 7daf24b41..32f304bef 100644 --- a/src/apps/main/remote-sync/RemoteSyncManager.ts +++ b/src/apps/main/remote-sync/RemoteSyncManager.ts @@ -128,7 +128,6 @@ export class RemoteSyncManager { await this.db.folders.connect(); Logger.info('Starting RemoteSyncManager'); - this.changeStatus('SYNCING'); try { const syncOptions = { retry: 1, diff --git a/src/apps/main/remote-sync/handlers.ts b/src/apps/main/remote-sync/handlers.ts index fc0a33457..fabf73c03 100644 --- a/src/apps/main/remote-sync/handlers.ts +++ b/src/apps/main/remote-sync/handlers.ts @@ -146,16 +146,17 @@ export async function updateRemoteSync(): Promise { // that we received the notification, but if we check // for new data we don't receive it Logger.info('Updating remote sync'); - const isSyncing = await checkSyncEngineInProcess(2_000); - if (isSyncing) { - Logger.info('Remote sync is already running'); - return; - } + const userData = configStore.get('userData'); const lastFilesSyncAt = await remoteSyncManager.getFileCheckpoint(); Logger.info('Last files sync at', lastFilesSyncAt); const folderId = lastFilesSyncAt ? undefined : userData?.root_folder_id; await startRemoteSync(folderId); + const isSyncing = await checkSyncEngineInProcess(2_000); + if (isSyncing) { + Logger.info('Remote sync is already running'); + return; + } updateSyncEngine(); } export async function fallbackRemoteSync(): Promise { diff --git a/src/apps/renderer/pages/Widget/index.tsx b/src/apps/renderer/pages/Widget/index.tsx index afae28a81..3f9bcd3d5 100644 --- a/src/apps/renderer/pages/Widget/index.tsx +++ b/src/apps/renderer/pages/Widget/index.tsx @@ -12,9 +12,9 @@ export default function Widget() { const [isLogoutModalOpen, setIsLogoutModalOpen] = useState(false); const handleRetrySync = () => { - // window.electron.startRemoteSync().catch((err) => { - // reportError(err); - // }); + window.electron.startRemoteSync().catch((err) => { + reportError(err); + }); }; const displayErrorInWidget = syncStatus && syncStatus === 'FAILED'; diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index ae7fb65c6..32cf5b1c5 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -330,10 +330,11 @@ export class BindingsManager { Logger.debug('[isTemporaryFile]', tempFile); - if (tempFile) { + if (tempFile && !task.isFolder) { Logger.debug('File is temporary, skipping'); return; } + ipcRenderer.send('RECEIVED_REMOTE_CHANGES'); const itemId = await this.controllers.addFile.execute(task.path); if (!itemId) { @@ -359,6 +360,8 @@ export class BindingsManager { try { const syncRoot = configStore.get('syncRoot'); Logger.debug('[Handle Hydrate Callback] Preparing begins', task.path); + const start = Date.now(); + const normalizePath = (path: string) => path.replace(/\\/g, '/'); const normalizedLastHydrated = normalizePath(this.lastHydrated); @@ -380,6 +383,12 @@ export class BindingsManager { await this.container.virtualDrive.hydrateFile(task.path); + const finish = Date.now(); + + if (finish - start < 1500) { + await new Promise((resolve) => setTimeout(resolve, 2000)); + } + Logger.debug('[Handle Hydrate Callback] Finish begins', task.path); } catch (error) { Logger.error(`error hydrating file ${task.path}`); diff --git a/src/context/virtual-drive/contents/infrastructure/FSLocalFileProvider.ts b/src/context/virtual-drive/contents/infrastructure/FSLocalFileProvider.ts index 1b5c373aa..b92317266 100644 --- a/src/context/virtual-drive/contents/infrastructure/FSLocalFileProvider.ts +++ b/src/context/virtual-drive/contents/infrastructure/FSLocalFileProvider.ts @@ -80,50 +80,56 @@ export class FSLocalFileProvider implements LocalContentsProvider { } async provide(absoluteFilePath: string) { - const { readable, controller } = await this.createAbortableStream( - absoluteFilePath - ); - - const { size, mtimeMs, birthtimeMs } = await fs.stat(absoluteFilePath); - - const absoluteFolderPath = path.dirname(absoluteFilePath); - const nameWithExtension = path.basename(absoluteFilePath); - - const watcher = watch(absoluteFolderPath, (_, filename) => { - if (filename !== nameWithExtension) { - return; - } - Logger.warn( - filename, - ' has been changed during read, it will be aborted' + try { + // Creación del stream con posibilidad de aborto + const { readable, controller } = await this.createAbortableStream( + absoluteFilePath ); - controller.abort(); - }); - - readable.on('end', () => { - watcher.close(); - this.reading.delete(absoluteFilePath); - }); - - readable.on('close', () => { - this.reading.delete(absoluteFilePath); - }); - - const [name, extension] = extractNameAndExtension(nameWithExtension); - - const contents = LocalFileContents.from({ - name, - extension, - size, - modifiedTime: mtimeMs, - birthTime: birthtimeMs, - contents: readable, - }); - - return { - contents, - abortSignal: controller.signal, - }; + const { size, mtimeMs, birthtimeMs } = await fs.stat(absoluteFilePath); + + const absoluteFolderPath = path.dirname(absoluteFilePath); + const nameWithExtension = path.basename(absoluteFilePath); + + const watcher = watch(absoluteFolderPath, (_, filename) => { + if (filename !== nameWithExtension) { + return; + } + Logger.warn( + filename, + ' has been changed during read, it will be aborted' + ); + + controller.abort(); + }); + + readable.on('end', () => { + watcher.close(); + this.reading.delete(absoluteFilePath); + }); + + readable.on('close', () => { + this.reading.delete(absoluteFilePath); + }); + + const [name, extension] = extractNameAndExtension(nameWithExtension); + + const contents = LocalFileContents.from({ + name, + extension, + size, + modifiedTime: mtimeMs, + birthTime: birthtimeMs, + contents: readable, + }); + + return { + contents, + abortSignal: controller.signal, + }; + } catch (error) { + Logger.error(`Error providing file: ${error}`); + throw error; + } } } From ffac4e1f7be53c224ff05f4741e31eaefd6458ed Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 18 Sep 2024 12:09:33 -0300 Subject: [PATCH 13/18] update package json --- package.json | 2 +- release/app/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index db1f5a3ee..e3d50aa68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.2", + "version": "2.1.3", "author": "Internxt ", "description": "Internxt Drive client UI", "license": "AGPL-3.0", diff --git a/release/app/package.json b/release/app/package.json index 1b9c48bd8..0e6eab0a6 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.2", + "version": "2.1.3", "description": "Internxt Drive client UI", "main": "./dist/main/main.js", "author": "Internxt ", From 7c5702464e9ab231dfa7c1447032141df62f025a Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Mon, 23 Sep 2024 13:34:47 -0300 Subject: [PATCH 14/18] delete log --- src/apps/main/auth/handlers.ts | 2 +- .../main/background-processes/sync-engine.ts | 2 -- .../main/remote-sync/RemoteSyncManager.ts | 6 ++-- .../infrastructure/HttpRemoteFolderSystem.ts | 29 ++++++++++++------- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/apps/main/auth/handlers.ts b/src/apps/main/auth/handlers.ts index fc6b49d0d..f605cf51c 100644 --- a/src/apps/main/auth/handlers.ts +++ b/src/apps/main/auth/handlers.ts @@ -66,7 +66,7 @@ ipcMain.on('user-logged-in', async (_, data: AccessResponse) => { if (!canHisConfigBeRestored(data.user.uuid)) { await setupRootFolder(); } - await await clearRootVirtualDrive(); + await clearRootVirtualDrive(); setIsLoggedIn(true); eventBus.emit('USER_LOGGED_IN'); diff --git a/src/apps/main/background-processes/sync-engine.ts b/src/apps/main/background-processes/sync-engine.ts index 0fab779af..12696a985 100644 --- a/src/apps/main/background-processes/sync-engine.ts +++ b/src/apps/main/background-processes/sync-engine.ts @@ -189,7 +189,6 @@ async function stopAndClearSyncEngineWatcher() { Logger.info('[MAIN] WORKER WAS NOT RUNNING'); worker?.destroy(); worker = null; - await clearRootVirtualDrive(); return; } @@ -232,7 +231,6 @@ async function stopAndClearSyncEngineWatcher() { worker?.destroy(); workerIsRunning = false; worker = null; - await clearRootVirtualDrive(); } } diff --git a/src/apps/main/remote-sync/RemoteSyncManager.ts b/src/apps/main/remote-sync/RemoteSyncManager.ts index 32f304bef..cd8eb8018 100644 --- a/src/apps/main/remote-sync/RemoteSyncManager.ts +++ b/src/apps/main/remote-sync/RemoteSyncManager.ts @@ -4,9 +4,9 @@ import { RemoteSyncedFolder, RemoteSyncedFile, SyncConfig, - FIVETEEN_MINUTES_IN_MILLISECONDS, rewind, WAITING_AFTER_SYNCING_DEFAULT, + SIX_HOURS_IN_MILLISECONDS, } from './helpers'; import { reportError } from '../bug-report/service'; @@ -251,7 +251,7 @@ export class RemoteSyncManager { const updatedAt = new Date(result.updatedAt); - return rewind(updatedAt, FIVETEEN_MINUTES_IN_MILLISECONDS); + return rewind(updatedAt, SIX_HOURS_IN_MILLISECONDS); } /** @@ -406,7 +406,7 @@ export class RemoteSyncManager { const updatedAt = new Date(result.updatedAt); - return rewind(updatedAt, FIVETEEN_MINUTES_IN_MILLISECONDS); + return rewind(updatedAt, SIX_HOURS_IN_MILLISECONDS); } private async syncRemoteFolders( diff --git a/src/context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem.ts b/src/context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem.ts index 1e350c13d..ae1fec613 100644 --- a/src/context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem.ts +++ b/src/context/virtual-drive/folders/infrastructure/HttpRemoteFolderSystem.ts @@ -146,19 +146,28 @@ export class HttpRemoteFolderSystem implements RemoteFolderSystem { } async rename(folder: Folder): Promise { - const url = `${process.env.API_URL}/storage/folder/${folder.id}/meta`; + try { + const url = `${process.env.API_URL}/storage/folder/${folder.id}/meta`; - const body: UpdateFolderNameDTO = { - metadata: { itemName: folder.name }, - relativePath: uuid.v4(), - }; + const body: UpdateFolderNameDTO = { + metadata: { itemName: folder.name }, + relativePath: uuid.v4(), + }; - const res = await this.driveClient.post(url, body); + const res = await this.driveClient.post(url, body); - if (res.status !== 200) { - throw new Error( - `[FOLDER FILE SYSTEM] Error updating item metadata: ${res.status}` - ); + if (res.status !== 200) { + throw new Error( + `[FOLDER FILE SYSTEM] Error updating item metadata: ${res.status}` + ); + } + } catch (error) { + Logger.error('[FOLDER FILE SYSTEM] Error renaming folder'); + if (axios.isAxiosError(error)) { + Logger.error('[Is Axios Error]', error.response?.data); + } + Sentry.captureException(error); + throw error; } } From 9bbd0d788c2a2369e43a897cebb9c70fb01f01fa Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 25 Sep 2024 16:17:42 -0300 Subject: [PATCH 15/18] Implemented the removal of items from the database once the server returns the correct status. Added a schedule to sync every 2 hours. --- .../main/background-processes/sync-engine.ts | 12 +- src/apps/main/database/adapters/base.ts | 8 ++ .../collections/DriveFileCollection.ts | 22 ++++ .../collections/DriveFolderCollection.ts | 21 ++++ .../main/remote-sync/RemoteSyncManager.ts | 4 +- src/apps/main/remote-sync/handlers.ts | 106 ++++++++++++++++++ src/apps/sync-engine/BindingManager.ts | 3 +- src/apps/utils/isTemporalFile.ts | 6 + .../application/FilesPlaceholderUpdater.ts | 23 ++++ .../application/UpdatePlaceholderFolder.ts | 17 +++ 10 files changed, 218 insertions(+), 4 deletions(-) diff --git a/src/apps/main/background-processes/sync-engine.ts b/src/apps/main/background-processes/sync-engine.ts index 12696a985..6a16012f5 100644 --- a/src/apps/main/background-processes/sync-engine.ts +++ b/src/apps/main/background-processes/sync-engine.ts @@ -5,12 +5,12 @@ import eventBus from '../event-bus'; import nodeSchedule from 'node-schedule'; import * as Sentry from '@sentry/electron/main'; import { checkSyncEngineInProcess } from '../remote-sync/handlers'; -import { clearRootVirtualDrive } from '../virtual-root-folder/service'; let worker: BrowserWindow | null = null; let workerIsRunning = false; let startingWorker = false; let healthCheckSchedule: nodeSchedule.Job | null = null; +let syncSchedule: nodeSchedule.Job | null = null; let attemptsAlreadyStarting = 0; ipcMain.once('SYNC_ENGINE_PROCESS_SETUP_SUCCESSFUL', () => { @@ -82,6 +82,15 @@ function scheduleHeathCheck() { } }); } +function scheduleSync() { + if (syncSchedule) { + syncSchedule.cancel(false); + } + + syncSchedule = nodeSchedule.scheduleJob('0 0 */2 * * *', async () => { + eventBus.emit('RECEIVED_REMOTE_CHANGES'); + }); +} function spawnSyncEngineWorker() { if (startingWorker) { @@ -113,6 +122,7 @@ function spawnSyncEngineWorker() { .then(() => { Logger.info('[MAIN] Sync engine worker loaded'); scheduleHeathCheck(); + scheduleSync(); }) .catch((err) => { Logger.error('[MAIN] Error loading sync engine worker', err); diff --git a/src/apps/main/database/adapters/base.ts b/src/apps/main/database/adapters/base.ts index b0622e5e9..b746965b9 100644 --- a/src/apps/main/database/adapters/base.ts +++ b/src/apps/main/database/adapters/base.ts @@ -41,4 +41,12 @@ export interface DatabaseCollectionAdapter { success: boolean; result: DatabaseItemType | null; }>; + + /** + * Gets items from partial data + */ + + searchPartialBy( + partialData: Partial + ): Promise<{ success: boolean; result: DatabaseItemType[] }>; } diff --git a/src/apps/main/database/collections/DriveFileCollection.ts b/src/apps/main/database/collections/DriveFileCollection.ts index 9c22ee07a..af69fe6ae 100644 --- a/src/apps/main/database/collections/DriveFileCollection.ts +++ b/src/apps/main/database/collections/DriveFileCollection.ts @@ -94,4 +94,26 @@ export class DriveFilesCollection }; } } + + async searchPartialBy( + partialData: Partial + ): Promise<{ success: boolean; result: DriveFile[] }> { + try { + Logger.info('Searching partial by', partialData); + const result = await this.repository.find({ + where: partialData, + }); + return { + success: true, + result, + }; + } catch (error) { + Sentry.captureException(error); + Logger.error('Error fetching drive folders:', error); + return { + success: false, + result: [], + }; + } + } } diff --git a/src/apps/main/database/collections/DriveFolderCollection.ts b/src/apps/main/database/collections/DriveFolderCollection.ts index c5fcf02a4..a95314b7e 100644 --- a/src/apps/main/database/collections/DriveFolderCollection.ts +++ b/src/apps/main/database/collections/DriveFolderCollection.ts @@ -93,4 +93,25 @@ export class DriveFoldersCollection }; } } + + async searchPartialBy( + partialData: Partial + ): Promise<{ success: boolean; result: DriveFolder[] }> { + try { + const result = await this.repository.find({ + where: partialData, + }); + return { + success: true, + result, + }; + } catch (error) { + Sentry.captureException(error); + Logger.error('Error fetching drive folders:', error); + return { + success: false, + result: [], + }; + } + } } diff --git a/src/apps/main/remote-sync/RemoteSyncManager.ts b/src/apps/main/remote-sync/RemoteSyncManager.ts index cd8eb8018..dfdf7c99a 100644 --- a/src/apps/main/remote-sync/RemoteSyncManager.ts +++ b/src/apps/main/remote-sync/RemoteSyncManager.ts @@ -142,11 +142,11 @@ export class RemoteSyncManager { ? this.syncRemoteFoldersByFolder(syncOptions, folderId) : this.syncRemoteFolders(syncOptions); - const [_files, folders] = await Promise.all([ + const [files, folders] = await Promise.all([ await syncFilesPromise, await syncFoldersPromise, ]); - return { files: _files, folders }; + return { files, folders }; } catch (error) { this.changeStatus('SYNC_FAILED'); reportError(error as Error); diff --git a/src/apps/main/remote-sync/handlers.ts b/src/apps/main/remote-sync/handlers.ts index fabf73c03..99302fab8 100644 --- a/src/apps/main/remote-sync/handlers.ts +++ b/src/apps/main/remote-sync/handlers.ts @@ -17,6 +17,8 @@ import { import { debounce } from 'lodash'; import configStore from '../config'; import { setTrayStatus } from '../tray/tray'; +import { FilePlaceholderId } from '../../../context/virtual-drive/files/domain/PlaceholderId'; +import { FolderPlaceholderId } from '../../../context/virtual-drive/folders/domain/FolderPlaceholderId'; const SYNC_DEBOUNCE_DELAY = 500; @@ -243,3 +245,107 @@ export async function checkSyncInProgress(milliSeconds: number) { ipcMain.handle('CHECK_SYNC_IN_PROGRESS', async (_, milliSeconds: number) => { return await checkSyncInProgress(milliSeconds); }); +// ipcMain.handle( +// 'DELETE_ITEM_DRIVE', +// async (_, itemId: FilePlaceholderId | FolderPlaceholderId) => { +// try { +// const [type, id] = itemId +// .replace( +// // eslint-disable-next-line no-control-regex +// /[\x00-\x1F\x7F-\x9F]/g, +// '' +// ) +// .normalize() +// .split(':'); + +// Logger.info('Deleting item in handler', itemId); +// Logger.info('Type and id', type, id); + +// const isFolder = type === 'FOLDER'; +// let result; +// if (isFolder) { +// result = await driveFoldersCollection.update(id, { status: 'TRASHED' }); +// } else { +// const item = await driveFilesCollection.searchPartialBy({ +// fileId: id, +// }); +// Logger.info('Item to delete', item); +// if (!item.result.length) return false; +// result = await driveFilesCollection.update(item.result[0].uuid, { +// status: 'TRASHED', +// }); +// } + +// Logger.info('Result deleting item in handler', result); +// return true; +// } catch (error) { +// Logger.error('Error deleting item in handler', error); +// return false; +// } +// } +// ); + +function parseItemId(itemId: string) { + const [type, id] = itemId + .replace( + // eslint-disable-next-line no-control-regex + /[\x00-\x1F\x7F-\x9F]/g, + '' + ) + .normalize() + .split(':'); + if (!type || !id) { + throw new Error(`Invalid itemId format: ${itemId}`); + } + return { type, id }; +} + +async function deleteFolder(folderId: string): Promise { + try { + const result = await driveFoldersCollection.update(folderId, { + status: 'TRASHED', + }); + return result.success; + } catch (error) { + Logger.error('Error deleting folder', { folderId, error }); + throw error; + } +} + +async function deleteFile(fileId: string): Promise { + try { + const item = await driveFilesCollection.searchPartialBy({ fileId }); + if (!item.result.length) { + Logger.warn('File not found', { fileId }); + return false; + } + const result = await driveFilesCollection.update(item.result[0].uuid, { + status: 'TRASHED', + }); + return result.success; + } catch (error) { + Logger.error('Error deleting file', { fileId, error }); + throw error; + } +} + +ipcMain.handle( + 'DELETE_ITEM_DRIVE', + async ( + _, + itemId: FilePlaceholderId | FolderPlaceholderId + ): Promise => { + try { + const { type, id } = parseItemId(itemId); + Logger.info('Deleting item in handler', { type, id }); + + const isFolder = type === 'FOLDER'; + const result = isFolder ? await deleteFolder(id) : await deleteFile(id); + + return result; + } catch (error) { + Logger.error('Error deleting item in handler', { error }); + return false; + } + } +); diff --git a/src/apps/sync-engine/BindingManager.ts b/src/apps/sync-engine/BindingManager.ts index 32cf5b1c5..dad60abf7 100644 --- a/src/apps/sync-engine/BindingManager.ts +++ b/src/apps/sync-engine/BindingManager.ts @@ -83,10 +83,12 @@ export class BindingsManager { contentsId: string, callback: (response: boolean) => void ) => { + Logger.debug('Path received from delete callback', contentsId); this.controllers.delete .execute(contentsId) .then(() => { callback(true); + ipcRenderer.invoke('DELETE_ITEM_DRIVE', contentsId); }) .catch((error: Error) => { Logger.error(error); @@ -334,7 +336,6 @@ export class BindingsManager { Logger.debug('File is temporary, skipping'); return; } - ipcRenderer.send('RECEIVED_REMOTE_CHANGES'); const itemId = await this.controllers.addFile.execute(task.path); if (!itemId) { diff --git a/src/apps/utils/isTemporalFile.ts b/src/apps/utils/isTemporalFile.ts index b8e0976fb..6fd2c147b 100644 --- a/src/apps/utils/isTemporalFile.ts +++ b/src/apps/utils/isTemporalFile.ts @@ -22,6 +22,12 @@ export const isTemporaryFile = async (filePath: string): Promise => { return true; } + // if start with $Recycle.Bin + if (filePath.includes('$Recycle.Bin')) { + Logger.debug(`File ${filePath} is in Recycle Bin`); + return true; + } + // Check if the file has the "TEMPORARY" attribute (Windows-specific) // const stats = await fs.promises.stat(filePath); // if (stats.isFile()) { diff --git a/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts b/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts index 3e672c5e6..ec3d7c7b7 100644 --- a/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts +++ b/src/context/virtual-drive/files/application/FilesPlaceholderUpdater.ts @@ -26,6 +26,24 @@ export class FilesPlaceholderUpdater { return localExists && (remoteIsTrashed || remoteIsDeleted); } + private async hasToBeCreated(remote: File): Promise { + const remoteExists = remote.status.is(FileStatuses.EXISTS); + const win32AbsolutePath = this.relativePathToAbsoluteConverter.run( + remote.path + ); + const existsFile = await this.fileExists(win32AbsolutePath); + return remoteExists && !existsFile; + } + + private async fileExists(win32AbsolutePath: string): Promise { + try { + await fs.stat(win32AbsolutePath); + return true; + } catch { + return false; + } + } + private async update(remote: File): Promise { const local = this.repository.searchByPartial({ contentsId: remote.contentsId, @@ -77,6 +95,11 @@ export class FilesPlaceholderUpdater { ); await fs.unlink(win32AbsolutePath); } + + if (await this.hasToBeCreated(remote)) { + await this.localFileSystem.createPlaceHolder(remote); + await this.repository.update(remote); + } } async run(remotes: Array): Promise { diff --git a/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts b/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts index 3426b026d..3a2170ef3 100644 --- a/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts +++ b/src/context/virtual-drive/folders/application/UpdatePlaceholderFolder.ts @@ -73,6 +73,18 @@ export class FolderPlaceholderUpdater { return localExists && (remoteIsTrashed || remoteIsDeleted); } + private async hasToBeCreated(remote: Folder): Promise { + const remoteExists = remote.status.is(FolderStatuses.EXISTS); + + const win32AbsolutePath = this.relativePathToAbsoluteConverter.run( + remote.path + ); + + const existsFolder = await this.folderExists(win32AbsolutePath); + + return remoteExists && !existsFolder; + } + private async update(remote: Folder): Promise { if (remote.path === path.posix.sep) { return; @@ -135,6 +147,11 @@ export class FolderPlaceholderUpdater { await fs.rm(win32AbsolutePath, { recursive: true }); return; } + + if (await this.hasToBeCreated(remote)) { + await this.local.createPlaceHolder(remote); + await this.repository.update(remote); + } } async run(remotes: Array): Promise { From 310b92bcf8749299a65e9a7518d658ea9f55cd2f Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Mon, 30 Sep 2024 11:30:17 -0300 Subject: [PATCH 16/18] delete comment and update rewind time --- src/apps/main/remote-sync/RemoteSyncManager.ts | 6 +++--- src/apps/utils/isTemporalFile.ts | 9 --------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/apps/main/remote-sync/RemoteSyncManager.ts b/src/apps/main/remote-sync/RemoteSyncManager.ts index dfdf7c99a..4e21632ab 100644 --- a/src/apps/main/remote-sync/RemoteSyncManager.ts +++ b/src/apps/main/remote-sync/RemoteSyncManager.ts @@ -6,7 +6,7 @@ import { SyncConfig, rewind, WAITING_AFTER_SYNCING_DEFAULT, - SIX_HOURS_IN_MILLISECONDS, + FIVETEEN_MINUTES_IN_MILLISECONDS, } from './helpers'; import { reportError } from '../bug-report/service'; @@ -251,7 +251,7 @@ export class RemoteSyncManager { const updatedAt = new Date(result.updatedAt); - return rewind(updatedAt, SIX_HOURS_IN_MILLISECONDS); + return rewind(updatedAt, FIVETEEN_MINUTES_IN_MILLISECONDS); } /** @@ -406,7 +406,7 @@ export class RemoteSyncManager { const updatedAt = new Date(result.updatedAt); - return rewind(updatedAt, SIX_HOURS_IN_MILLISECONDS); + return rewind(updatedAt, FIVETEEN_MINUTES_IN_MILLISECONDS); } private async syncRemoteFolders( diff --git a/src/apps/utils/isTemporalFile.ts b/src/apps/utils/isTemporalFile.ts index 6fd2c147b..b22cf01ed 100644 --- a/src/apps/utils/isTemporalFile.ts +++ b/src/apps/utils/isTemporalFile.ts @@ -1,8 +1,6 @@ -import * as fs from 'fs'; import * as path from 'path'; import Logger from 'electron-log'; -// Function to check if the file is marked as temporary by the OS (Windows example) export const isTemporaryFile = async (filePath: string): Promise => { try { // Check if the file name starts with a common temporary prefix @@ -27,13 +25,6 @@ export const isTemporaryFile = async (filePath: string): Promise => { Logger.debug(`File ${filePath} is in Recycle Bin`); return true; } - - // Check if the file has the "TEMPORARY" attribute (Windows-specific) - // const stats = await fs.promises.stat(filePath); - // if (stats.isFile()) { - // return stats.mode !== 0; - // } - return false; } catch (error) { Logger.error(`Failed to check if the file is temporary: ${error}`); From c762018b4eabac6d2876685aac05d7fd415266e5 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 2 Oct 2024 12:54:20 -0300 Subject: [PATCH 17/18] delete get usage photo --- src/apps/main/usage/service.ts | 6 +++--- src/apps/renderer/hooks/useUsage.tsx | 1 - .../infrastrucutre/CachedHttpUserUsageRepository.ts | 8 +++----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/apps/main/usage/service.ts b/src/apps/main/usage/service.ts index 4fd6a2fef..2fc215c6b 100644 --- a/src/apps/main/usage/service.ts +++ b/src/apps/main/usage/service.ts @@ -11,8 +11,8 @@ export class UserUsageService { ) {} private async getPhotosUsage(): Promise { - const { usage } = await this.photos.getUsage(); - return usage; + // const { usage } = await this.photos.getUsage(); + return 0; } private async getDriveUsage(): Promise { @@ -28,7 +28,7 @@ export class UserUsageService { } async calculateUsage(): Promise { - const [driveUsage, photosUsage, limitInBytes] = await Promise.all([ + const [driveUsage, photosUsage, limitInBytes] = await Promise.all([ this.getDriveUsage(), this.getPhotosUsage(), this.getLimit(), diff --git a/src/apps/renderer/hooks/useUsage.tsx b/src/apps/renderer/hooks/useUsage.tsx index 2ab83a2d8..fd75cbf4d 100644 --- a/src/apps/renderer/hooks/useUsage.tsx +++ b/src/apps/renderer/hooks/useUsage.tsx @@ -18,7 +18,6 @@ export default function useUsage() { setUsage(usage); setStatus('ready'); } catch (err) { - console.error(err); setStatus('error'); } } diff --git a/src/context/virtual-drive/userUsage/infrastrucutre/CachedHttpUserUsageRepository.ts b/src/context/virtual-drive/userUsage/infrastrucutre/CachedHttpUserUsageRepository.ts index 7f5d1f222..8c9a4d056 100644 --- a/src/context/virtual-drive/userUsage/infrastrucutre/CachedHttpUserUsageRepository.ts +++ b/src/context/virtual-drive/userUsage/infrastrucutre/CachedHttpUserUsageRepository.ts @@ -13,9 +13,7 @@ export class CachedHttpUserUsageRepository implements UserUsageRepository { ) {} private async getDriveUsage(): Promise { - const response = await this.driveClient.get( - `${process.env.API_URL}/usage` - ); + const response = await this.driveClient.get(`${process.env.API_URL}/usage`); if (response.status !== 200) { throw new Error('Error retriving drive usage'); @@ -40,12 +38,12 @@ export class CachedHttpUserUsageRepository implements UserUsageRepository { if (this.cahdedUserUsage) return this.cahdedUserUsage; const drive = await this.getDriveUsage(); - const { usage: photos } = await this.photosSubmodule.getUsage(); + // const { usage: photos } = await this.photosSubmodule.getUsage(); const limit = await this.getLimit(); const usage = UserUsage.from({ drive, - photos, + photos: 0, limit, }); From f578d2a1949fa9c8093f794f9b647425d473fb77 Mon Sep 17 00:00:00 2001 From: ArceDanielShok Date: Wed, 2 Oct 2024 12:57:27 -0300 Subject: [PATCH 18/18] update version --- package.json | 2 +- release/app/package.json | 2 +- .../virtual-drive/folders/application/FolderDeleter.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e3d50aa68..c8e332400 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.3", + "version": "2.1.4", "author": "Internxt ", "description": "Internxt Drive client UI", "license": "AGPL-3.0", diff --git a/release/app/package.json b/release/app/package.json index 0e6eab0a6..372b9411f 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "internxt-drive", - "version": "2.1.3", + "version": "2.1.4", "description": "Internxt Drive client UI", "main": "./dist/main/main.js", "author": "Internxt ", diff --git a/src/context/virtual-drive/folders/application/FolderDeleter.ts b/src/context/virtual-drive/folders/application/FolderDeleter.ts index 3293e753a..8c825123d 100644 --- a/src/context/virtual-drive/folders/application/FolderDeleter.ts +++ b/src/context/virtual-drive/folders/application/FolderDeleter.ts @@ -4,13 +4,13 @@ import { ActionNotPermittedError } from '../domain/errors/ActionNotPermittedErro import { FolderNotFoundError } from '../domain/errors/FolderNotFoundError'; import { AllParentFoldersStatusIsExists } from './AllParentFoldersStatusIsExists'; import { FolderRepository } from '../domain/FolderRepository'; -import { RemoteFileSystem } from '../domain/file-systems/RemoteFolderSystem'; +import { RemoteFolderSystem } from '../domain/file-systems/RemoteFolderSystem'; import { LocalFolderSystem } from '../domain/file-systems/LocalFolderSystem'; export class FolderDeleter { constructor( private readonly repository: FolderRepository, - private readonly remote: RemoteFileSystem, + private readonly remote: RemoteFolderSystem, private readonly local: LocalFolderSystem, private readonly allParentFoldersStatusIsExists: AllParentFoldersStatusIsExists ) {}