refactor: handle detect faces job query (#17660)

This commit is contained in:
Daniel Dietzler
2025-04-16 22:52:54 +02:00
committed by GitHub
parent 1bbfacfc09
commit 586a7a173b
5 changed files with 80 additions and 32 deletions
+23 -25
View File
@@ -1,5 +1,4 @@
import { BadRequestException, NotFoundException } from '@nestjs/common';
import { AssetFace } from 'src/database';
import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto';
import { mapFaces, mapPerson, PersonResponseDto } from 'src/dtos/person.dto';
import { CacheControl, Colorspace, ImageFormat, JobName, JobStatus, SourceType, SystemMetadataKey } from 'src/enum';
@@ -719,24 +718,7 @@ describe(PersonService.name, () => {
});
it('should skip when no resize path', async () => {
mocks.asset.getByIds.mockResolvedValue([assetStub.noResizePath]);
await sut.handleDetectFaces({ id: assetStub.noResizePath.id });
expect(mocks.machineLearning.detectFaces).not.toHaveBeenCalled();
});
it('should skip it the asset has already been processed', async () => {
mocks.asset.getByIds.mockResolvedValue([
{
...assetStub.noResizePath,
faces: [
{
id: 'asset-face-1',
assetId: assetStub.noResizePath.id,
personId: faceStub.face1.personId,
} as AssetFace,
],
},
]);
mocks.assetJob.getForDetectFacesJob.mockResolvedValue({ ...assetStub.noResizePath, files: [] });
await sut.handleDetectFaces({ id: assetStub.noResizePath.id });
expect(mocks.machineLearning.detectFaces).not.toHaveBeenCalled();
});
@@ -745,7 +727,7 @@ describe(PersonService.name, () => {
const start = Date.now();
mocks.machineLearning.detectFaces.mockResolvedValue({ imageHeight: 500, imageWidth: 400, faces: [] });
mocks.asset.getByIds.mockResolvedValue([assetStub.image]);
mocks.assetJob.getForDetectFacesJob.mockResolvedValue({ ...assetStub.image, files: [assetStub.image.files[1]] });
await sut.handleDetectFaces({ id: assetStub.image.id });
expect(mocks.machineLearning.detectFaces).toHaveBeenCalledWith(
['http://immich-machine-learning:3003'],
@@ -766,7 +748,7 @@ describe(PersonService.name, () => {
it('should create a face with no person and queue recognition job', async () => {
mocks.machineLearning.detectFaces.mockResolvedValue(detectFaceMock);
mocks.search.searchFaces.mockResolvedValue([{ ...faceStub.face1, distance: 0.7 }]);
mocks.asset.getByIds.mockResolvedValue([assetStub.image]);
mocks.assetJob.getForDetectFacesJob.mockResolvedValue({ ...assetStub.image, files: [assetStub.image.files[1]] });
mocks.person.refreshFaces.mockResolvedValue();
await sut.handleDetectFaces({ id: assetStub.image.id });
@@ -782,7 +764,11 @@ describe(PersonService.name, () => {
it('should delete an existing face not among the new detected faces', async () => {
mocks.machineLearning.detectFaces.mockResolvedValue({ faces: [], imageHeight: 500, imageWidth: 400 });
mocks.asset.getByIds.mockResolvedValue([{ ...assetStub.image, faces: [faceStub.primaryFace1] }]);
mocks.assetJob.getForDetectFacesJob.mockResolvedValue({
...assetStub.image,
faces: [faceStub.primaryFace1],
files: [assetStub.image.files[1]],
});
await sut.handleDetectFaces({ id: assetStub.image.id });
@@ -794,7 +780,11 @@ describe(PersonService.name, () => {
it('should add new face and delete an existing face not among the new detected faces', async () => {
mocks.machineLearning.detectFaces.mockResolvedValue(detectFaceMock);
mocks.asset.getByIds.mockResolvedValue([{ ...assetStub.image, faces: [faceStub.primaryFace1] }]);
mocks.assetJob.getForDetectFacesJob.mockResolvedValue({
...assetStub.image,
faces: [faceStub.primaryFace1],
files: [assetStub.image.files[1]],
});
mocks.person.refreshFaces.mockResolvedValue();
await sut.handleDetectFaces({ id: assetStub.image.id });
@@ -810,7 +800,11 @@ describe(PersonService.name, () => {
it('should add embedding to matching metadata face', async () => {
mocks.machineLearning.detectFaces.mockResolvedValue(detectFaceMock);
mocks.asset.getByIds.mockResolvedValue([{ ...assetStub.image, faces: [faceStub.fromExif1] }]);
mocks.assetJob.getForDetectFacesJob.mockResolvedValue({
...assetStub.image,
faces: [faceStub.fromExif1],
files: [assetStub.image.files[1]],
});
mocks.person.refreshFaces.mockResolvedValue();
await sut.handleDetectFaces({ id: assetStub.image.id });
@@ -827,7 +821,11 @@ describe(PersonService.name, () => {
it('should not add embedding to non-matching metadata face', async () => {
mocks.machineLearning.detectFaces.mockResolvedValue(detectFaceMock);
mocks.asset.getByIds.mockResolvedValue([{ ...assetStub.image, faces: [faceStub.fromExif2] }]);
mocks.assetJob.getForDetectFacesJob.mockResolvedValue({
...assetStub.image,
faces: [faceStub.fromExif2],
files: [assetStub.image.files[1]],
});
await sut.handleDetectFaces({ id: assetStub.image.id });