From 8c8b11f80c09487b86fef271417677f6dacceb9c Mon Sep 17 00:00:00 2001 From: Brandon Wees Date: Tue, 10 Feb 2026 11:38:43 -0600 Subject: [PATCH] fix: person thumbnail generation on edited assets (#26112) * fix: person thumbnail generation on edited assets * chore: sql sync --- server/src/queries/person.repository.sql | 3 +- server/src/repositories/person.repository.ts | 1 + .../repositories/person.repository.spec.ts | 68 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 server/test/medium/specs/repositories/person.repository.spec.ts diff --git a/server/src/queries/person.repository.sql b/server/src/queries/person.repository.sql index 356f5af8f6..59f0f12424 100644 --- a/server/src/queries/person.repository.sql +++ b/server/src/queries/person.repository.sql @@ -176,6 +176,7 @@ select where "asset_file"."assetId" = "asset"."id" and "asset_file"."type" = 'preview' + and "asset_file"."isEdited" = $1 ) as "previewPath" from "person" @@ -183,7 +184,7 @@ from inner join "asset" on "asset_face"."assetId" = "asset"."id" left join "asset_exif" on "asset_exif"."assetId" = "asset"."id" where - "person"."id" = $1 + "person"."id" = $2 and "asset_face"."deletedAt" is null -- PersonRepository.reassignFace diff --git a/server/src/repositories/person.repository.ts b/server/src/repositories/person.repository.ts index b03112821b..85e75483c5 100644 --- a/server/src/repositories/person.repository.ts +++ b/server/src/repositories/person.repository.ts @@ -288,6 +288,7 @@ export class PersonRepository { .select('asset_file.path') .whereRef('asset_file.assetId', '=', 'asset.id') .where('asset_file.type', '=', sql.lit(AssetFileType.Preview)) + .where('asset_file.isEdited', '=', false) .as('previewPath'), ) .where('person.id', '=', id) diff --git a/server/test/medium/specs/repositories/person.repository.spec.ts b/server/test/medium/specs/repositories/person.repository.spec.ts new file mode 100644 index 0000000000..30f0fd33c0 --- /dev/null +++ b/server/test/medium/specs/repositories/person.repository.spec.ts @@ -0,0 +1,68 @@ +import { Kysely } from 'kysely'; +import { AssetFileType } from 'src/enum'; +import { LoggingRepository } from 'src/repositories/logging.repository'; +import { PersonRepository } from 'src/repositories/person.repository'; +import { DB } from 'src/schema'; +import { BaseService } from 'src/services/base.service'; +import { newMediumService } from 'test/medium.factory'; +import { getKyselyDB } from 'test/utils'; + +let defaultDatabase: Kysely; + +const setup = (db?: Kysely) => { + const { ctx } = newMediumService(BaseService, { + database: db || defaultDatabase, + real: [], + mock: [LoggingRepository], + }); + return { ctx, sut: ctx.get(PersonRepository) }; +}; + +beforeAll(async () => { + defaultDatabase = await getKyselyDB(); +}); + +describe(PersonRepository.name, () => { + describe('getDataForThumbnailGenerationJob', () => { + it('should not return the edited preview path', async () => { + const { ctx, sut } = setup(); + const { user } = await ctx.newUser(); + + const { asset } = await ctx.newAsset({ ownerId: user.id }); + const { person } = await ctx.newPerson({ ownerId: user.id }); + + const { assetFace } = await ctx.newAssetFace({ + assetId: asset.id, + personId: person.id, + boundingBoxX1: 10, + boundingBoxY1: 10, + boundingBoxX2: 90, + boundingBoxY2: 90, + }); + + // theres a circular dependency between assetFace and person, so we need to update the person after creating the assetFace + await ctx.database.updateTable('person').set({ faceAssetId: assetFace.id }).where('id', '=', person.id).execute(); + + await ctx.newAssetFile({ + assetId: asset.id, + type: AssetFileType.Preview, + path: 'preview_edited.jpg', + isEdited: true, + }); + await ctx.newAssetFile({ + assetId: asset.id, + type: AssetFileType.Preview, + path: 'preview_unedited.jpg', + isEdited: false, + }); + + const result = await sut.getDataForThumbnailGenerationJob(person.id); + + expect(result).toEqual( + expect.objectContaining({ + previewPath: 'preview_unedited.jpg', + }), + ); + }); + }); +});