refactor(media-upload): lazy-load relations

Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
David Mehren 2021-11-18 18:47:12 +01:00
parent 8aae5cb574
commit facdc456cd
No known key found for this signature in database
GPG key ID: 185982BA4C42B7C3
9 changed files with 39 additions and 30 deletions

View file

@ -40,7 +40,9 @@ export class MeController {
@Get('media')
async getMyMedia(@RequestUser() user: User): Promise<MediaUploadDto[]> {
const media = await this.mediaService.listUploadsByUser(user);
return media.map((media) => this.mediaService.toMediaUploadDto(media));
return await Promise.all(
media.map((media) => this.mediaService.toMediaUploadDto(media)),
);
}
@Delete()

View file

@ -131,7 +131,7 @@ export class MediaController {
const mediaUpload = await this.mediaService.findUploadByFilename(
filename,
);
if (mediaUpload.user.username !== username) {
if ((await mediaUpload.user).username !== username) {
this.logger.warn(
`${username} tried to delete '${filename}', but is not the owner`,
'deleteMedia',

View file

@ -72,7 +72,9 @@ export class NotesController {
@UseGuards(PermissionsGuard)
async getNotesMedia(@RequestNote() note: Note): Promise<MediaUploadDto[]> {
const media = await this.mediaService.listUploadsByNote(note);
return media.map((media) => this.mediaService.toMediaUploadDto(media));
return await Promise.all(
media.map((media) => this.mediaService.toMediaUploadDto(media)),
);
}
@Post()

View file

@ -188,6 +188,8 @@ export class MeController {
@ApiUnauthorizedResponse({ description: unauthorizedDescription })
async getMyMedia(@RequestUser() user: User): Promise<MediaUploadDto[]> {
const media = await this.mediaService.listUploadsByUser(user);
return media.map((media) => this.mediaService.toMediaUploadDto(media));
return await Promise.all(
media.map((media) => this.mediaService.toMediaUploadDto(media)),
);
}
}

View file

@ -136,7 +136,7 @@ export class MediaController {
const mediaUpload = await this.mediaService.findUploadByFilename(
filename,
);
if (mediaUpload.user.username !== username) {
if ((await mediaUpload.user).username !== username) {
this.logger.warn(
`${username} tried to delete '${filename}', but is not the owner`,
'deleteMedia',

View file

@ -298,6 +298,8 @@ export class NotesController {
@RequestNote() note: Note,
): Promise<MediaUploadDto[]> {
const media = await this.mediaService.listUploadsByNote(note);
return media.map((media) => this.mediaService.toMediaUploadDto(media));
return await Promise.all(
media.map((media) => this.mediaService.toMediaUploadDto(media)),
);
}
}

View file

@ -25,12 +25,12 @@ export class MediaUpload {
@ManyToOne((_) => Note, (note) => note.mediaUploads, {
nullable: true,
})
note: Note | null;
note: Promise<Note | null>;
@ManyToOne((_) => User, (user) => user.mediaUploads, {
nullable: false,
})
user: User;
user: Promise<User>;
@Column({
nullable: false,
@ -72,8 +72,8 @@ export class MediaUpload {
): Omit<MediaUpload, 'createdAt'> {
const upload = new MediaUpload();
upload.id = id;
upload.note = note;
upload.user = user;
upload.note = Promise.resolve(note);
upload.user = Promise.resolve(user);
upload.backendType = backendType;
upload.backendData = null;
upload.fileUrl = fileUrl;

View file

@ -167,9 +167,9 @@ describe('MediaService', () => {
const mockMediaUploadEntry = {
id: 'testMediaUpload',
backendData: 'testBackendData',
user: {
user: Promise.resolve({
username: 'hardcoded',
} as User,
} as User),
} as MediaUpload;
jest
.spyOn(service.mediaBackend, 'deleteFile')
@ -196,15 +196,15 @@ describe('MediaService', () => {
const mockMediaUploadEntry = {
id: 'testMediaUpload',
backendData: backendData,
user: {
user: Promise.resolve({
username: username,
} as User,
} as User),
} as MediaUpload;
jest
.spyOn(mediaRepo, 'findOne')
.mockResolvedValueOnce(mockMediaUploadEntry);
const mediaUpload = await service.findUploadByFilename(testFileName);
expect(mediaUpload.user.username).toEqual(username);
expect((await mediaUpload.user).username).toEqual(username);
expect(mediaUpload.backendData).toEqual(backendData);
});
it("fails: can't find mediaUpload", async () => {
@ -218,13 +218,14 @@ describe('MediaService', () => {
describe('listUploadsByUser', () => {
describe('works', () => {
const username = 'hardcoded';
it('with one upload from user', async () => {
const mockMediaUploadEntry = {
id: 'testMediaUpload',
backendData: 'testBackendData',
user: {
username: 'hardcoded',
} as User,
user: Promise.resolve({
username: username,
} as User),
} as MediaUpload;
jest
.spyOn(mediaRepo, 'find')
@ -237,14 +238,14 @@ describe('MediaService', () => {
it('without uploads from user', async () => {
jest.spyOn(mediaRepo, 'find').mockResolvedValueOnce([]);
const mediaList = await service.listUploadsByUser({
username: 'hardcoded',
username: username,
} as User);
expect(mediaList).toEqual([]);
});
it('with error (undefined as return value of find)', async () => {
jest.spyOn(mediaRepo, 'find').mockResolvedValueOnce(undefined);
const mediaList = await service.listUploadsByUser({
username: 'hardcoded',
username: username,
} as User);
expect(mediaList).toEqual([]);
});
@ -257,9 +258,9 @@ describe('MediaService', () => {
const mockMediaUploadEntry = {
id: 'testMediaUpload',
backendData: 'testBackendData',
note: {
note: Promise.resolve({
id: '123',
} as Note,
} as Note),
} as MediaUpload;
jest
.spyOn(mediaRepo, 'find')
@ -294,15 +295,15 @@ describe('MediaService', () => {
const mockMediaUploadEntry = {
id: 'testMediaUpload',
backendData: 'testBackendData',
note: mockNote,
user: {
note: Promise.resolve(mockNote),
user: Promise.resolve({
username: 'hardcoded',
} as User,
} as User),
} as MediaUpload;
jest
.spyOn(mediaRepo, 'save')
.mockImplementationOnce(async (entry: MediaUpload) => {
expect(entry.note).toBeNull();
expect(await entry.note).toBeNull();
return entry;
});
await service.removeNoteFromMediaUpload(mockMediaUploadEntry);

View file

@ -181,7 +181,7 @@ export class MediaService {
'Setting note to null for mediaUpload: ' + mediaUpload.id,
'removeNoteFromMediaUpload',
);
mediaUpload.note = null;
mediaUpload.note = Promise.resolve(null);
await this.mediaUploadRepository.save(mediaUpload);
}
@ -219,12 +219,12 @@ export class MediaService {
}
}
toMediaUploadDto(mediaUpload: MediaUpload): MediaUploadDto {
async toMediaUploadDto(mediaUpload: MediaUpload): Promise<MediaUploadDto> {
return {
url: mediaUpload.fileUrl,
noteId: mediaUpload.note?.id ?? null,
noteId: (await mediaUpload.note)?.id ?? null,
createdAt: mediaUpload.createdAt,
username: mediaUpload.user.username,
username: (await mediaUpload.user).username,
};
}