Skip to content

Commit

Permalink
feat: query now can be requested with only existent files
Browse files Browse the repository at this point in the history
  • Loading branch information
apsantiso committed Jun 25, 2024
1 parent 42b1146 commit 3722474
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 9 deletions.
19 changes: 17 additions & 2 deletions src/modules/folder/folder.repository.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SequelizeFolderRepository } from './folder.repository';
import { FolderModel } from './folder.model';
import { Folder } from './folder.domain';
import { newFolder } from '../../../test/fixtures';
import { FileStatus } from '../file/file.domain';

jest.mock('./folder.model', () => ({
FolderModel: {
Expand Down Expand Up @@ -39,7 +40,7 @@ describe('SequelizeFolderRepository', () => {
1 AS row_num,
fl1.user_id as owner_id
FROM folders fl1
LEFT JOIN files f1 ON f1.folder_uuid = fl1.uuid AND f1.status != 'DELETED'
LEFT JOIN files f1 ON f1.folder_uuid = fl1.uuid AND f1.status IN (:fileStatusCondition)
WHERE fl1.uuid = :folderUuid
AND fl1.removed = FALSE
AND fl1.deleted = FALSE
Expand All @@ -53,7 +54,7 @@ describe('SequelizeFolderRepository', () => {
fr.row_num + 1,
fr.owner_id
FROM folders fl2
LEFT JOIN files f2 ON f2.folder_uuid = fl2.uuid AND f2.status != 'DELETED'
LEFT JOIN files f2 ON f2.folder_uuid = fl2.uuid AND f2.status IN (:fileStatusCondition)
INNER JOIN folder_recursive fr ON fr.uuid = fl2.parent_uuid
WHERE fr.row_num < 100000
AND fl2.user_id = fr.owner_id
Expand All @@ -75,11 +76,25 @@ describe('SequelizeFolderRepository', () => {
{
replacements: {
folderUuid: folder.uuid,
fileStatusCondition: [FileStatus.EXISTS, FileStatus.TRASHED],
},
},
);
});

it('When calculate folder size is requested without trashed files, then it should only request existent files', async () => {
const folderModelSpy = jest.spyOn(FolderModel.sequelize, 'query');

await repository.calculateFolderSize(folder.uuid, false);

expect(folderModelSpy).toHaveBeenCalledWith(expect.any(String), {
replacements: {
folderUuid: folder.uuid,
fileStatusCondition: [FileStatus.EXISTS],
},
});
});

it('When the folder size calculation times out, then throw an exception', async () => {
jest.spyOn(FolderModel.sequelize, 'query').mockRejectedValue({
original: {
Expand Down
15 changes: 12 additions & 3 deletions src/modules/folder/folder.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FolderModel } from './folder.model';
import { SharingModel } from '../sharing/models';
import { CalculateFolderSizeTimeoutException } from './exception/calculate-folder-size-timeout.exception';
import { Literal } from 'sequelize/types/utils';
import { FileStatus } from '../file/file.domain';

function mapSnakeCaseToCamelCase(data) {
const camelCasedObject = {};
Expand Down Expand Up @@ -515,8 +516,15 @@ export class SequelizeFolderRepository implements FolderRepository {
return folders.map((folder) => this.toDomain(folder));
}

async calculateFolderSize(folderUuid: string): Promise<number> {
async calculateFolderSize(
folderUuid: string,
includeTrash = true,
): Promise<number> {
try {
const fileStatusCondition = includeTrash
? [FileStatus.EXISTS, FileStatus.TRASHED]
: [FileStatus.EXISTS];

const calculateSizeQuery = `
WITH RECURSIVE folder_recursive AS (
SELECT
Expand All @@ -526,7 +534,7 @@ export class SequelizeFolderRepository implements FolderRepository {
1 AS row_num,
fl1.user_id as owner_id
FROM folders fl1
LEFT JOIN files f1 ON f1.folder_uuid = fl1.uuid AND f1.status != 'DELETED'
LEFT JOIN files f1 ON f1.folder_uuid = fl1.uuid AND f1.status IN (:fileStatusCondition)
WHERE fl1.uuid = :folderUuid
AND fl1.removed = FALSE
AND fl1.deleted = FALSE
Expand All @@ -540,7 +548,7 @@ export class SequelizeFolderRepository implements FolderRepository {
fr.row_num + 1,
fr.owner_id
FROM folders fl2
LEFT JOIN files f2 ON f2.folder_uuid = fl2.uuid AND f2.status != 'DELETED'
LEFT JOIN files f2 ON f2.folder_uuid = fl2.uuid AND f2.status IN (:fileStatusCondition)
INNER JOIN folder_recursive fr ON fr.uuid = fl2.parent_uuid
WHERE fr.row_num < 100000
AND fl2.user_id = fr.owner_id
Expand All @@ -555,6 +563,7 @@ export class SequelizeFolderRepository implements FolderRepository {
{
replacements: {
folderUuid,
fileStatusCondition,
},
},
);
Expand Down
18 changes: 18 additions & 0 deletions src/modules/folder/folder.usecase.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,24 @@ describe('FolderUseCases', () => {
expect(folderRepository.calculateFolderSize).toHaveBeenCalledTimes(1);
expect(folderRepository.calculateFolderSize).toHaveBeenCalledWith(
folder.uuid,
true,
);
});

it('When the folder size is required without including trashed files, then it should request the size without trash', async () => {
const mockSize = 123456789;

jest
.spyOn(folderRepository, 'calculateFolderSize')
.mockResolvedValueOnce(mockSize);

const result = await service.getFolderSizeByUuid(folder.uuid, false);

expect(result).toBe(mockSize);
expect(folderRepository.calculateFolderSize).toHaveBeenCalledTimes(1);
expect(folderRepository.calculateFolderSize).toHaveBeenCalledWith(
folder.uuid,
false,
);
});

Expand Down
14 changes: 11 additions & 3 deletions src/modules/folder/folder.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,9 @@ export class FolderUseCases {
const folders = foldersById.concat(foldersByUuid);

const backups = folders.filter((f) => f.isBackup(driveRootFolder));
const driveFolders = folders.filter((f) => !f.isBackup(driveRootFolder) && f.id !== user.rootFolderId);
const driveFolders = folders.filter(
(f) => !f.isBackup(driveRootFolder) && f.id !== user.rootFolderId,
);

await Promise.all([
driveFolders.length > 0
Expand Down Expand Up @@ -632,7 +634,13 @@ export class FolderUseCases {
await this.folderRepository.deleteByUser(user, folders);
}

getFolderSizeByUuid(folderUuid: Folder['uuid']): Promise<number> {
return this.folderRepository.calculateFolderSize(folderUuid);
getFolderSizeByUuid(
folderUuid: Folder['uuid'],
includeTrashedFiles = true,
): Promise<number> {
return this.folderRepository.calculateFolderSize(
folderUuid,
includeTrashedFiles,
);
}
}
2 changes: 1 addition & 1 deletion src/modules/sharing/sharing.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,6 @@ export class SharingService {
throw new SharingNotFoundException();
}

return this.folderUsecases.getFolderSizeByUuid(sharing.itemId);
return this.folderUsecases.getFolderSizeByUuid(sharing.itemId, false);
}
}

0 comments on commit 3722474

Please sign in to comment.