From 010eb1e0d6da353fa727209959966a4e1a56fb85 Mon Sep 17 00:00:00 2001 From: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Date: Sun, 16 Jun 2024 17:37:51 +0200 Subject: [PATCH] fix(server): include trashed assets in forced thumbnail generation (#10389) * fix(server): include trashed assets in forced thumbnail generation * deleted -> trashed --- server/src/services/media.service.spec.ts | 25 ++++++++++++++ server/src/services/media.service.ts | 2 +- server/test/fixtures/asset.stub.ts | 40 +++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index ef08f059a3..d5bda48fbb 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -107,6 +107,31 @@ describe(MediaService.name, () => { ]); }); + it('should queue trashed assets when force is true', async () => { + assetMock.getAll.mockResolvedValue({ + items: [assetStub.trashed], + hasNextPage: false, + }); + personMock.getAll.mockResolvedValue({ + items: [], + hasNextPage: false, + }); + + await sut.handleQueueGenerateThumbnails({ force: true }); + + expect(assetMock.getAll).toHaveBeenCalledWith( + { skip: 0, take: 1000 }, + expect.objectContaining({ withDeleted: true }), + ); + expect(assetMock.getWithout).not.toHaveBeenCalled(); + expect(jobMock.queueAll).toHaveBeenCalledWith([ + { + name: JobName.GENERATE_PREVIEW, + data: { id: assetStub.trashed.id }, + }, + ]); + }); + it('should queue all people with missing thumbnail path', async () => { assetMock.getWithout.mockResolvedValue({ items: [assetStub.image], diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index fc1f16a638..6e5778c4df 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -70,7 +70,7 @@ export class MediaService { async handleQueueGenerateThumbnails({ force }: IBaseJob): Promise { const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { return force - ? this.assetRepository.getAll(pagination, { isVisible: true }) + ? this.assetRepository.getAll(pagination, { isVisible: true, withDeleted: true }) : this.assetRepository.getWithout(pagination, WithoutProperty.THUMBNAIL); }); diff --git a/server/test/fixtures/asset.stub.ts b/server/test/fixtures/asset.stub.ts index 01d5e8c119..70075669e6 100644 --- a/server/test/fixtures/asset.stub.ts +++ b/server/test/fixtures/asset.stub.ts @@ -209,6 +209,46 @@ export const assetStub = { duplicateId: null, }), + trashed: Object.freeze({ + id: 'asset-id', + deviceAssetId: 'device-asset-id', + fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'), + fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'), + owner: userStub.user1, + ownerId: 'user-id', + deviceId: 'device-id', + originalPath: '/original/path.jpg', + previewPath: '/uploads/user-id/thumbs/path.jpg', + checksum: Buffer.from('file hash', 'utf8'), + type: AssetType.IMAGE, + thumbnailPath: '/uploads/user-id/webp/path.ext', + thumbhash: Buffer.from('blablabla', 'base64'), + encodedVideoPath: null, + createdAt: new Date('2023-02-23T05:06:29.716Z'), + updatedAt: new Date('2023-02-23T05:06:29.716Z'), + deletedAt: new Date('2023-02-24T05:06:29.716Z'), + localDateTime: new Date('2023-02-23T05:06:29.716Z'), + isFavorite: false, + isArchived: false, + duration: null, + isVisible: true, + isExternal: false, + livePhotoVideo: null, + livePhotoVideoId: null, + isOffline: false, + tags: [], + sharedLinks: [], + originalFileName: 'asset-id.jpg', + faces: [], + sidecarPath: null, + exifInfo: { + fileSizeInByte: 5000, + exifImageHeight: 3840, + exifImageWidth: 2160, + } as ExifEntity, + duplicateId: null, + }), + external: Object.freeze({ id: 'asset-id', deviceAssetId: 'device-asset-id',