From 6d1cb35d35d578d6d2e24391e36bfbd9dc7cc62c Mon Sep 17 00:00:00 2001 From: migueldev01 Date: Thu, 18 Jan 2024 09:51:49 -0500 Subject: [PATCH 1/2] *add retry mechanism to try deleting folder *add logic to delete queue events --- .../callbacks-controllers/buildControllers.ts | 4 +- .../controllers/DeleteController.ts | 51 +++++++++++++++++-- .../files/FilesContainer.ts | 2 + .../dependency-injection/files/builder.ts | 7 +++ .../folders/FoldersContainer.ts | 4 ++ .../dependency-injection/folders/builder.ts | 8 +++ src/apps/sync-engine/index.ts | 3 ++ .../files/application/FileDeleter.ts | 4 +- .../FileFolderContainerDetector.ts | 18 +++++++ .../application/FolderContainerDetector.ts | 27 ++++++++++ .../folders/application/FolderFinder.ts | 8 +++ .../Offline/OfflineFolderCreator.ts | 2 + .../folders/application/RetryFolderDeleter.ts | 50 ++++++++++++++++++ .../errors/MaxRetriesDeletingFolderError.ts | 5 ++ .../virtual-drive/shared/domain/DelayQueue.ts | 31 ++++++++--- 15 files changed, 207 insertions(+), 17 deletions(-) create mode 100644 src/context/virtual-drive/files/application/FileFolderContainerDetector.ts create mode 100644 src/context/virtual-drive/folders/application/FolderContainerDetector.ts create mode 100644 src/context/virtual-drive/folders/application/RetryFolderDeleter.ts create mode 100644 src/context/virtual-drive/folders/domain/errors/MaxRetriesDeletingFolderError.ts diff --git a/src/apps/sync-engine/callbacks-controllers/buildControllers.ts b/src/apps/sync-engine/callbacks-controllers/buildControllers.ts index 1f749a02d..d4ea27b56 100644 --- a/src/apps/sync-engine/callbacks-controllers/buildControllers.ts +++ b/src/apps/sync-engine/callbacks-controllers/buildControllers.ts @@ -16,7 +16,9 @@ export function buildControllers(container: DependencyContainer) { const deleteController = new DeleteController( container.fileDeleter, - container.folderDeleter + container.retryFolderDeleter, + container.fileFolderContainerDetector, + container.folderContainerDetector ); const renameOrMoveController = new RenameOrMoveController( diff --git a/src/apps/sync-engine/callbacks-controllers/controllers/DeleteController.ts b/src/apps/sync-engine/callbacks-controllers/controllers/DeleteController.ts index 65ee7fa18..f6be1e79d 100644 --- a/src/apps/sync-engine/callbacks-controllers/controllers/DeleteController.ts +++ b/src/apps/sync-engine/callbacks-controllers/controllers/DeleteController.ts @@ -1,8 +1,11 @@ import { FileDeleter } from '../../../../context/virtual-drive/files/application/FileDeleter'; -import { FolderDeleter } from '../../../../context/virtual-drive/folders/application/FolderDeleter'; +import { RetryFolderDeleter } from '../../../../context/virtual-drive/folders/application/RetryFolderDeleter'; import { DelayQueue } from '../../../../context/virtual-drive/shared/domain/DelayQueue'; import { CallbackController } from './CallbackController'; import Logger from 'electron-log'; +import { FileFolderContainerDetector } from '../../../../context/virtual-drive/files/application/FileFolderContainerDetector'; +import { Folder } from '../../../../context/virtual-drive/folders/domain/Folder'; +import { FolderContainerDetector } from '../../../../context/virtual-drive/folders/application/FolderContainerDetector'; export class DeleteController extends CallbackController { private readonly filesQueue: DelayQueue; @@ -10,7 +13,9 @@ export class DeleteController extends CallbackController { constructor( private readonly fileDeleter: FileDeleter, - private readonly folderDeleter: FolderDeleter + private readonly retryFolderDeleter: RetryFolderDeleter, + private readonly fileFolderContainerDetector: FileFolderContainerDetector, + private readonly folderContainerDetector: FolderContainerDetector ) { super(); @@ -19,7 +24,12 @@ export class DeleteController extends CallbackController { }; const deleteFolder = async (folder: string) => { - await this.folderDeleter.run(folder); + try { + await this.retryFolderDeleter.run(folder); + } catch (error) { + Logger.error('Error deleting folder: ', error); + // TODO: create tree of placeholders that are not deleted + } }; const canDeleteFolders = () => { @@ -34,8 +44,7 @@ export class DeleteController extends CallbackController { ); const canDeleteFiles = () => { - // Files cannot be deleted if there are folders on the queue - return this.foldersQueue.size === 0; + return this.foldersQueue.isEmpty; }; this.filesQueue = new DelayQueue('files', deleteFile, canDeleteFiles); @@ -54,10 +63,42 @@ export class DeleteController extends CallbackController { if (this.isFolderPlaceholder(trimmedId)) { const [_, folderUuid] = trimmedId.split(':'); Logger.debug(`Adding folder: ${folderUuid} to the trash queue`); + this.CleanQueuesByFolder(folderUuid); this.foldersQueue.push(folderUuid); return; } throw new Error(`Placeholder Id not identified: ${trimmedId}`); } + + private CleanQueuesByFolder(folderUuid: Folder['uuid']) { + // always remove files from the filesQueue if a folder is added + this.CleanQueueFile(folderUuid); + // remove child folders from the queue if a parent folder exists + this.CleanQueueFolder(folderUuid); + } + + private CleanQueueFile(folderUuid: Folder['uuid']) { + const files = this.filesQueue.values; + const filesToDelete = files.filter((file) => + this.fileFolderContainerDetector.run(file, folderUuid) + ); + filesToDelete.forEach((file) => { + this.filesQueue.removeOne(file); + }); + } + + private CleanQueueFolder(folderUuid: Folder['uuid']) { + const folders = this.foldersQueue.values; + const reversedFolders = folders.reverse(); + reversedFolders.forEach((folder) => { + const isParentFolder = this.folderContainerDetector.run( + folder, + folderUuid + ); + if (isParentFolder) { + this.foldersQueue.removeOne(folder); + } + }); + } } diff --git a/src/apps/sync-engine/dependency-injection/files/FilesContainer.ts b/src/apps/sync-engine/dependency-injection/files/FilesContainer.ts index 5ba634247..ea7334e25 100644 --- a/src/apps/sync-engine/dependency-injection/files/FilesContainer.ts +++ b/src/apps/sync-engine/dependency-injection/files/FilesContainer.ts @@ -9,10 +9,12 @@ import { FilesPlaceholderCreator } from '../../../../context/virtual-drive/files import { RepositoryPopulator } from '../../../../context/virtual-drive/files/application/RepositoryPopulator'; import { RetrieveAllFiles } from '../../../../context/virtual-drive/files/application/RetrieveAllFiles'; import { SameFileWasMoved } from '../../../../context/virtual-drive/files/application/SameFileWasMoved'; +import { FileFolderContainerDetector } from '../../../../context/virtual-drive/files/application/FileFolderContainerDetector'; export interface FilesContainer { fileFinderByContentsId: FileFinderByContentsId; fileDeleter: FileDeleter; + fileFolderContainerDetector: FileFolderContainerDetector; filePathUpdater: FilePathUpdater; fileCreator: FileCreator; filePlaceholderCreatorFromContentsId: FilePlaceholderCreatorFromContentsId; diff --git a/src/apps/sync-engine/dependency-injection/files/builder.ts b/src/apps/sync-engine/dependency-injection/files/builder.ts index e9cf5c424..2b1bfb434 100644 --- a/src/apps/sync-engine/dependency-injection/files/builder.ts +++ b/src/apps/sync-engine/dependency-injection/files/builder.ts @@ -24,6 +24,7 @@ import { SDKRemoteFileSystem } from '../../../../context/virtual-drive/files/inf import { NodeWinLocalFileSystem } from '../../../../context/virtual-drive/files/infrastructure/NodeWinLocalFileSystem'; import { LocalFileIdProvider } from '../../../../context/virtual-drive/shared/application/LocalFileIdProvider'; import { DependencyInjectionHttpClientsProvider } from '../common/clients'; +import { FileFolderContainerDetector } from '../../../../context/virtual-drive/files/application/FileFolderContainerDetector'; export async function buildFilesContainer( folderContainer: FoldersContainer, @@ -63,6 +64,11 @@ export async function buildFilesContainer( ipcRendererSyncEngine ); + const fileFolderContainerDetector = new FileFolderContainerDetector( + repository, + folderContainer.folderFinder + ); + const sameFileWasMoved = new SameFileWasMoved( repository, localFileSystem, @@ -120,6 +126,7 @@ export async function buildFilesContainer( fileDeleter, filePathUpdater, fileCreator, + fileFolderContainerDetector, filePlaceholderCreatorFromContentsId: filePlaceholderCreatorFromContentsId, createFilePlaceholderOnDeletionFailed: createFilePlaceholderOnDeletionFailed, diff --git a/src/apps/sync-engine/dependency-injection/folders/FoldersContainer.ts b/src/apps/sync-engine/dependency-injection/folders/FoldersContainer.ts index bcb774e3d..10de3f7ce 100644 --- a/src/apps/sync-engine/dependency-injection/folders/FoldersContainer.ts +++ b/src/apps/sync-engine/dependency-injection/folders/FoldersContainer.ts @@ -1,5 +1,6 @@ import { AllParentFoldersStatusIsExists } from '../../../../context/virtual-drive/folders/application/AllParentFoldersStatusIsExists'; import { FolderByPartialSearcher } from '../../../../context/virtual-drive/folders/application/FolderByPartialSearcher'; +import { FolderContainerDetector } from '../../../../context/virtual-drive/folders/application/FolderContainerDetector'; import { FolderCreator } from '../../../../context/virtual-drive/folders/application/FolderCreator'; import { FolderDeleter } from '../../../../context/virtual-drive/folders/application/FolderDeleter'; import { FolderFinder } from '../../../../context/virtual-drive/folders/application/FolderFinder'; @@ -9,6 +10,7 @@ import { FoldersPlaceholderCreator } from '../../../../context/virtual-drive/fol import { OfflineFolderCreator } from '../../../../context/virtual-drive/folders/application/Offline/OfflineFolderCreator'; import { OfflineFolderPathUpdater } from '../../../../context/virtual-drive/folders/application/Offline/OfflineFolderPathUpdater'; import { RetrieveAllFolders } from '../../../../context/virtual-drive/folders/application/RetrieveAllFolders'; +import { RetryFolderDeleter } from '../../../../context/virtual-drive/folders/application/RetryFolderDeleter'; 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'; @@ -16,7 +18,9 @@ import { FolderPlaceholderUpdater } from '../../../../context/virtual-drive/fold export interface FoldersContainer { folderCreator: FolderCreator; folderFinder: FolderFinder; + folderContainerDetector: FolderContainerDetector; folderDeleter: FolderDeleter; + retryFolderDeleter: RetryFolderDeleter; allParentFoldersStatusIsExists: AllParentFoldersStatusIsExists; folderPathUpdater: FolderPathUpdater; folderByPartialSearcher: FolderByPartialSearcher; diff --git a/src/apps/sync-engine/dependency-injection/folders/builder.ts b/src/apps/sync-engine/dependency-injection/folders/builder.ts index b40d16044..f68151366 100644 --- a/src/apps/sync-engine/dependency-injection/folders/builder.ts +++ b/src/apps/sync-engine/dependency-injection/folders/builder.ts @@ -27,6 +27,8 @@ import { DependencyInjectionEventRepository } from '../common/eventRepository'; import { DependencyInjectionVirtualDrive } from '../common/virtualDrive'; import { SharedContainer } from '../shared/SharedContainer'; import { FoldersContainer } from './FoldersContainer'; +import { RetryFolderDeleter } from '../../../../context/virtual-drive/folders/application/RetryFolderDeleter'; +import { FolderContainerDetector } from '../../../../context/virtual-drive/folders/application/FolderContainerDetector'; export async function buildFoldersContainer( shredContainer: SharedContainer @@ -57,6 +59,8 @@ export async function buildFoldersContainer( allParentFoldersStatusIsExists ); + const retryFolderDeleter = new RetryFolderDeleter(folderDeleter); + const folderCreator = new FolderCreator( repository, remoteFileSystem, @@ -124,12 +128,16 @@ export async function buildFoldersContainer( shredContainer.relativePathToAbsoluteConverter ); + const folderContainerDetector = new FolderContainerDetector(repository); + return { folderCreator, folderFinder, folderDeleter, + retryFolderDeleter, allParentFoldersStatusIsExists: allParentFoldersStatusIsExists, folderPathUpdater, + folderContainerDetector, folderByPartialSearcher, synchronizeOfflineModificationsOnFolderCreated, offline: { diff --git a/src/apps/sync-engine/index.ts b/src/apps/sync-engine/index.ts index c5ea70358..61b7814aa 100644 --- a/src/apps/sync-engine/index.ts +++ b/src/apps/sync-engine/index.ts @@ -81,5 +81,8 @@ setUp() }) .catch((error) => { Logger.error('[SYNC ENGINE] Error setting up', error); + if (error.toString().includes('Error: ConnectSyncRoot failed')) { + Logger.info('[SYNC ENGINE] We neeed to restart the app virtual drive'); + } ipcRenderer.send('SYNC_ENGINE_PROCESS_SETUP_FAILED'); }); diff --git a/src/context/virtual-drive/files/application/FileDeleter.ts b/src/context/virtual-drive/files/application/FileDeleter.ts index 70ac81bfd..185232c63 100644 --- a/src/context/virtual-drive/files/application/FileDeleter.ts +++ b/src/context/virtual-drive/files/application/FileDeleter.ts @@ -65,7 +65,7 @@ export class FileDeleter { ); const message = error instanceof Error ? error.message : 'Unknown error'; - + this.local.createPlaceHolder(file); this.ipc.send('FILE_DELETION_ERROR', { name: file.name, extension: file.type, @@ -80,8 +80,6 @@ export class FileDeleter { errorName: 'BAD_RESPONSE', process: 'SYNC', }); - - this.local.createPlaceHolder(file); } } } diff --git a/src/context/virtual-drive/files/application/FileFolderContainerDetector.ts b/src/context/virtual-drive/files/application/FileFolderContainerDetector.ts new file mode 100644 index 000000000..b9b2cd822 --- /dev/null +++ b/src/context/virtual-drive/files/application/FileFolderContainerDetector.ts @@ -0,0 +1,18 @@ +import { FolderFinder } from '../../folders/application/FolderFinder'; +import { File } from '../../files/domain/File'; +import { Folder } from '../../folders/domain/Folder'; +import { FileRepository } from '../domain/FileRepository'; + +export class FileFolderContainerDetector { + constructor( + private readonly repository: FileRepository, + private readonly folderFinder: FolderFinder + ) {} + + run(contentId: File['contentsId'], folderContentId: Folder['uuid']): boolean { + const file = this.repository.searchByPartial({ contentsId: contentId }); + const folder = this.folderFinder.findFromId(file?.folderId); + const [_, folderUuid] = folder.placeholderId.split(':'); + return folderUuid === folderContentId; + } +} diff --git a/src/context/virtual-drive/folders/application/FolderContainerDetector.ts b/src/context/virtual-drive/folders/application/FolderContainerDetector.ts new file mode 100644 index 000000000..14221aa69 --- /dev/null +++ b/src/context/virtual-drive/folders/application/FolderContainerDetector.ts @@ -0,0 +1,27 @@ +import { Folder } from '../domain/Folder'; +import { FolderRepository } from '../domain/FolderRepository'; + +export class FolderContainerDetector { + constructor(private readonly repository: FolderRepository) {} + + run( + fodlerContentId: Folder['uuid'], + parentFolderContentId: Folder['uuid'] + ): boolean { + const folder = this.repository.searchByPartial({ uuid: fodlerContentId }); + + if (!folder) { + throw new Error('Folder not found'); + } + + const parent = this.repository.searchByPartial({ + id: folder.parentId as number, + }); + + if (!parent) { + throw new Error('Parent folder not found'); + } + + return parent.uuid === parentFolderContentId; + } +} diff --git a/src/context/virtual-drive/folders/application/FolderFinder.ts b/src/context/virtual-drive/folders/application/FolderFinder.ts index 8f50d9b46..6db686c50 100644 --- a/src/context/virtual-drive/folders/application/FolderFinder.ts +++ b/src/context/virtual-drive/folders/application/FolderFinder.ts @@ -25,4 +25,12 @@ export class FolderFinder { return folder; } + + findFromId(id: Folder['id'] | undefined): Folder { + const folder = this.repository.searchByPartial({ id }); + if (!folder) { + throw new Error('Folder not found'); + } + return folder; + } } diff --git a/src/context/virtual-drive/folders/application/Offline/OfflineFolderCreator.ts b/src/context/virtual-drive/folders/application/Offline/OfflineFolderCreator.ts index 30650be19..9bd900a35 100644 --- a/src/context/virtual-drive/folders/application/Offline/OfflineFolderCreator.ts +++ b/src/context/virtual-drive/folders/application/Offline/OfflineFolderCreator.ts @@ -3,6 +3,7 @@ import { OfflineFolder } from '../../domain/OfflineFolder'; import { OfflineFolderRepository } from '../../domain/OfflineFolderRepository'; import { FolderFinder } from '../FolderFinder'; import { FolderRepository } from '../../domain/FolderRepository'; +import { FolderStatuses } from '../../domain/FolderStatus'; export class OfflineFolderCreator { constructor( @@ -16,6 +17,7 @@ export class OfflineFolderCreator { const onlineFolder = this.repository.searchByPartial({ path: folderPath.value, + status: FolderStatuses.EXISTS, }); if (onlineFolder) { diff --git a/src/context/virtual-drive/folders/application/RetryFolderDeleter.ts b/src/context/virtual-drive/folders/application/RetryFolderDeleter.ts new file mode 100644 index 000000000..e4f6a9dc6 --- /dev/null +++ b/src/context/virtual-drive/folders/application/RetryFolderDeleter.ts @@ -0,0 +1,50 @@ +import Logger from 'electron-log'; +import { FolderDeleter } from './FolderDeleter'; +import { MaxRetriesDeletingFolderError } from '../domain/errors/MaxRetriesDeletingFolderError'; + +export class RetryFolderDeleter { + private static NUMBER_OF_RETRIES = 2; + private static MILLISECOND_BETWEEN_TRIES = 1_000; + private static INITIAL_DELAY = 100; + constructor(private readonly deleter: FolderDeleter) {} + async retryDeleter(asyncFunction: () => Promise) { + let retryCount = 0; + + while (retryCount <= RetryFolderDeleter.NUMBER_OF_RETRIES) { + try { + const result = await asyncFunction(); + return result; + } catch (error: unknown) { + if (error instanceof Error) { + Logger.warn( + `Folder deleter attempt ${retryCount + 1} failed: ${error.message}` + ); + } else { + Logger.warn( + `Folder deleter attempt ${ + retryCount + 1 + } failed with an unknown error.` + ); + } + + await new Promise((resolve) => { + setTimeout(resolve, RetryFolderDeleter.MILLISECOND_BETWEEN_TRIES); + }); + + retryCount++; + } + } + throw new MaxRetriesDeletingFolderError( + RetryFolderDeleter.NUMBER_OF_RETRIES + ); + } + + async run(folder: string): Promise { + await new Promise((resolve) => { + setTimeout(resolve, RetryFolderDeleter.INITIAL_DELAY); + }); + + const deleter = () => this.deleter.run(folder); + return this.retryDeleter(deleter); + } +} diff --git a/src/context/virtual-drive/folders/domain/errors/MaxRetriesDeletingFolderError.ts b/src/context/virtual-drive/folders/domain/errors/MaxRetriesDeletingFolderError.ts new file mode 100644 index 000000000..0d79a399f --- /dev/null +++ b/src/context/virtual-drive/folders/domain/errors/MaxRetriesDeletingFolderError.ts @@ -0,0 +1,5 @@ +export class MaxRetriesDeletingFolderError extends Error { + constructor(retriesNumber: number) { + super(`Max retries (${retriesNumber}) reached. Deleter still failed.`); + } +} diff --git a/src/context/virtual-drive/shared/domain/DelayQueue.ts b/src/context/virtual-drive/shared/domain/DelayQueue.ts index dd7a44c34..19b31f561 100644 --- a/src/context/virtual-drive/shared/domain/DelayQueue.ts +++ b/src/context/virtual-drive/shared/domain/DelayQueue.ts @@ -20,26 +20,29 @@ export class DelayQueue { } } - private setTimeout() { + private setTimeout(delay = DelayQueue.DELAY) { this.clearTimeout(); this.timeout = setTimeout(async () => { Logger.debug('Will try to run delay queue for: ', this.name); if (this.canLoop()) { Logger.debug('Running delay queue for: ', this.name); - const reversedItems = Array.from(this.queue.entries()).reverse(); - - for (const [item] of reversedItems) { - await this.fn(item); - this.queue.delete(item); + await this.executeFn(reversedItems[0][0]); + if (!this.isEmpty) { + Logger.debug('Restarting delay queue is not empty'); + this.setTimeout(500); } - return; } Logger.debug(this.name, 'delay queue blocked'); this.setTimeout(); - }, DelayQueue.DELAY); + }, delay); + } + + private async executeFn(item: string) { + this.queue.delete(item); + await this.fn(item); } push(value: string) { @@ -56,4 +59,16 @@ export class DelayQueue { this.clearTimeout(); this.queue.clear(); } + + removeOne(value: string) { + this.queue.delete(value); + } + + get values(): string[] { + return Array.from(this.queue.keys()); + } + + get isEmpty(): boolean { + return this.queue.size === 0; + } } From e5d858aebcb42aa411ae3a9879a53cedb33e160f Mon Sep 17 00:00:00 2001 From: migueldev01 Date: Thu, 8 Feb 2024 23:19:01 -0500 Subject: [PATCH 2/2] **smeller code **rollback master-erb --- .../controllers/DeleteController.ts | 3 +-- .../application/FileFolderContainerDetector.ts | 13 +++++++++---- .../folders/application/FolderFinder.ts | 2 +- .../virtual-drive/shared/domain/DelayQueue.ts | 4 ++++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/apps/sync-engine/callbacks-controllers/controllers/DeleteController.ts b/src/apps/sync-engine/callbacks-controllers/controllers/DeleteController.ts index f6be1e79d..defc439df 100644 --- a/src/apps/sync-engine/callbacks-controllers/controllers/DeleteController.ts +++ b/src/apps/sync-engine/callbacks-controllers/controllers/DeleteController.ts @@ -89,8 +89,7 @@ export class DeleteController extends CallbackController { } private CleanQueueFolder(folderUuid: Folder['uuid']) { - const folders = this.foldersQueue.values; - const reversedFolders = folders.reverse(); + const reversedFolders = this.foldersQueue.reversedValues; reversedFolders.forEach((folder) => { const isParentFolder = this.folderContainerDetector.run( folder, diff --git a/src/context/virtual-drive/files/application/FileFolderContainerDetector.ts b/src/context/virtual-drive/files/application/FileFolderContainerDetector.ts index b9b2cd822..b27794f66 100644 --- a/src/context/virtual-drive/files/application/FileFolderContainerDetector.ts +++ b/src/context/virtual-drive/files/application/FileFolderContainerDetector.ts @@ -2,6 +2,7 @@ import { FolderFinder } from '../../folders/application/FolderFinder'; import { File } from '../../files/domain/File'; import { Folder } from '../../folders/domain/Folder'; import { FileRepository } from '../domain/FileRepository'; +import { FileNotFoundError } from '../domain/errors/FileNotFoundError'; export class FileFolderContainerDetector { constructor( @@ -10,9 +11,13 @@ export class FileFolderContainerDetector { ) {} run(contentId: File['contentsId'], folderContentId: Folder['uuid']): boolean { - const file = this.repository.searchByPartial({ contentsId: contentId }); - const folder = this.folderFinder.findFromId(file?.folderId); - const [_, folderUuid] = folder.placeholderId.split(':'); - return folderUuid === folderContentId; + const file = this.repository.searchByPartial({ + contentsId: contentId, + }); + if (!file) { + throw new FileNotFoundError(contentId); + } + const folder = this.folderFinder.findFromId(file.folderId); + return folder.uuid === folderContentId; } } diff --git a/src/context/virtual-drive/folders/application/FolderFinder.ts b/src/context/virtual-drive/folders/application/FolderFinder.ts index 6db686c50..5aaae4d39 100644 --- a/src/context/virtual-drive/folders/application/FolderFinder.ts +++ b/src/context/virtual-drive/folders/application/FolderFinder.ts @@ -26,7 +26,7 @@ export class FolderFinder { return folder; } - findFromId(id: Folder['id'] | undefined): Folder { + findFromId(id: Folder['id']): Folder { const folder = this.repository.searchByPartial({ id }); if (!folder) { throw new Error('Folder not found'); diff --git a/src/context/virtual-drive/shared/domain/DelayQueue.ts b/src/context/virtual-drive/shared/domain/DelayQueue.ts index 19b31f561..63f17a6e8 100644 --- a/src/context/virtual-drive/shared/domain/DelayQueue.ts +++ b/src/context/virtual-drive/shared/domain/DelayQueue.ts @@ -68,6 +68,10 @@ export class DelayQueue { return Array.from(this.queue.keys()); } + get reversedValues(): string[] { + return Array.from(this.queue.keys()).reverse(); + } + get isEmpty(): boolean { return this.queue.size === 0; }