diff --git a/server/src/queries/asset.job.repository.sql b/server/src/queries/asset.job.repository.sql index 5e28f2c4c9..7c2db418a4 100644 --- a/server/src/queries/asset.job.repository.sql +++ b/server/src/queries/asset.job.repository.sql @@ -183,6 +183,16 @@ from where "assets"."id" = $1 +-- AssetJobRepository.getAlbumThumbnailFile +select + "asset_files"."id", + "asset_files"."path", + "asset_files"."type" +from + "asset_files" +where + "asset_files"."assetId" = $1 + -- AssetJobRepository.getForStorageTemplateJob select "assets"."id", diff --git a/server/src/repositories/asset-job.repository.ts b/server/src/repositories/asset-job.repository.ts index 770ca93891..480972a8ae 100644 --- a/server/src/repositories/asset-job.repository.ts +++ b/server/src/repositories/asset-job.repository.ts @@ -117,6 +117,11 @@ export class AssetJobRepository { .executeTakeFirst(); } + @GenerateSql({ params: [DummyValue.UUID] }) + getAlbumThumbnailFile(id: string) { + return this.db.selectFrom('asset_files').select(columns.assetFiles).where('asset_files.assetId', '=', id).execute(); + } + private storageTemplateAssetQuery() { return this.db .selectFrom('assets') diff --git a/server/src/services/notification.service.spec.ts b/server/src/services/notification.service.spec.ts index c9a6f593ba..45663b4aa2 100644 --- a/server/src/services/notification.service.spec.ts +++ b/server/src/services/notification.service.spec.ts @@ -412,11 +412,12 @@ describe(NotificationService.name, () => { }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.assetJob.getAlbumThumbnailFile.mockResolvedValue([]); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.SUCCESS); - expect(mocks.asset.getById).toHaveBeenCalledWith(albumStub.emptyWithValidThumbnail.albumThumbnailAssetId, { - files: true, - }); + expect(mocks.assetJob.getAlbumThumbnailFile).toHaveBeenCalledWith( + albumStub.emptyWithValidThumbnail.albumThumbnailAssetId, + ); expect(mocks.job.queue).toHaveBeenCalledWith({ name: JobName.SEND_EMAIL, data: expect.objectContaining({ @@ -439,15 +440,14 @@ describe(NotificationService.name, () => { }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); - mocks.asset.getById.mockResolvedValue({ - ...assetStub.image, - files: [{ id: '1', type: AssetFileType.THUMBNAIL, path: 'path-to-thumb.jpg' }], - }); + mocks.assetJob.getAlbumThumbnailFile.mockResolvedValue([ + { id: '1', type: AssetFileType.THUMBNAIL, path: 'path-to-thumb.jpg' }, + ]); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.SUCCESS); - expect(mocks.asset.getById).toHaveBeenCalledWith(albumStub.emptyWithValidThumbnail.albumThumbnailAssetId, { - files: true, - }); + expect(mocks.assetJob.getAlbumThumbnailFile).toHaveBeenCalledWith( + albumStub.emptyWithValidThumbnail.albumThumbnailAssetId, + ); expect(mocks.job.queue).toHaveBeenCalledWith({ name: JobName.SEND_EMAIL, data: expect.objectContaining({ @@ -470,12 +470,12 @@ describe(NotificationService.name, () => { }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); - mocks.asset.getById.mockResolvedValue(assetStub.image); + mocks.assetJob.getAlbumThumbnailFile.mockResolvedValue(assetStub.image.files); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.SUCCESS); - expect(mocks.asset.getById).toHaveBeenCalledWith(albumStub.emptyWithValidThumbnail.albumThumbnailAssetId, { - files: true, - }); + expect(mocks.assetJob.getAlbumThumbnailFile).toHaveBeenCalledWith( + albumStub.emptyWithValidThumbnail.albumThumbnailAssetId, + ); expect(mocks.job.queue).toHaveBeenCalledWith({ name: JobName.SEND_EMAIL, data: expect.objectContaining({ @@ -506,6 +506,7 @@ describe(NotificationService.name, () => { }); mocks.user.get.mockResolvedValueOnce(userStub.user1); mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.assetJob.getAlbumThumbnailFile.mockResolvedValue([]); await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); expect(mocks.user.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); @@ -527,6 +528,7 @@ describe(NotificationService.name, () => { ], }); mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.assetJob.getAlbumThumbnailFile.mockResolvedValue([]); await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); expect(mocks.user.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); @@ -548,6 +550,7 @@ describe(NotificationService.name, () => { ], }); mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.assetJob.getAlbumThumbnailFile.mockResolvedValue([]); await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); expect(mocks.user.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); @@ -561,6 +564,7 @@ describe(NotificationService.name, () => { }); mocks.user.get.mockResolvedValue(userStub.user1); mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.assetJob.getAlbumThumbnailFile.mockResolvedValue([]); await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); expect(mocks.user.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); diff --git a/server/src/services/notification.service.ts b/server/src/services/notification.service.ts index dcec865f89..9396681bfe 100644 --- a/server/src/services/notification.service.ts +++ b/server/src/services/notification.service.ts @@ -1,7 +1,6 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; -import { AlbumEntity } from 'src/entities/album.entity'; import { AssetFileType, JobName, JobStatus, QueueName } from 'src/enum'; import { ArgOf } from 'src/repositories/event.repository'; import { EmailTemplate } from 'src/repositories/notification.repository'; @@ -392,17 +391,19 @@ export class NotificationService extends BaseService { return JobStatus.SUCCESS; } - private async getAlbumThumbnailAttachment(album: AlbumEntity): Promise { + private async getAlbumThumbnailAttachment(album: { + albumThumbnailAssetId: string | null; + }): Promise { if (!album.albumThumbnailAssetId) { return; } - const albumThumbnail = await this.assetRepository.getById(album.albumThumbnailAssetId, { files: true }); - if (!albumThumbnail) { + const albumThumbnailFiles = await this.assetJobRepository.getAlbumThumbnailFile(album.albumThumbnailAssetId); + if (albumThumbnailFiles.length === 0) { return; } - const thumbnailFile = getAssetFile(albumThumbnail.files, AssetFileType.THUMBNAIL); + const thumbnailFile = getAssetFile(albumThumbnailFiles, AssetFileType.THUMBNAIL); if (!thumbnailFile) { return; }