Skip to content

Commit

Permalink
feat(server): optimize face re-queueing (#6961)
Browse files Browse the repository at this point in the history
* do not defer faces with no matches

* move comment
  • Loading branch information
mertalev committed Feb 7, 2024
1 parent 479fca8 commit b31c768
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 7 deletions.
31 changes: 26 additions & 5 deletions server/src/domain/person/person.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -866,11 +866,29 @@ describe(PersonService.name, () => {
});
});

it('should defer non-core faces to end of queue', async () => {
it('should not queue face with no matches', async () => {
const faces = [{ face: faceStub.noPerson1, distance: 0 }] as FaceSearchResult[];

smartInfoMock.searchFaces.mockResolvedValue(faces);
personMock.getFaceByIdWithAssets.mockResolvedValue(faceStub.noPerson1);
personMock.create.mockResolvedValue(personStub.withName);

await sut.handleRecognizeFaces({ id: faceStub.noPerson1.id });

expect(jobMock.queue).not.toHaveBeenCalled();
expect(smartInfoMock.searchFaces).toHaveBeenCalledTimes(1);
expect(personMock.create).not.toHaveBeenCalled();
expect(personMock.reassignFaces).not.toHaveBeenCalled();
});

it('should defer non-core faces to end of queue', async () => {
const faces = [
{ face: faceStub.noPerson1, distance: 0 },
{ face: faceStub.noPerson2, distance: 0.4 },
] as FaceSearchResult[];

configMock.load.mockResolvedValue([
{ key: SystemConfigKey.MACHINE_LEARNING_FACIAL_RECOGNITION_MIN_FACES, value: 2 },
{ key: SystemConfigKey.MACHINE_LEARNING_FACIAL_RECOGNITION_MIN_FACES, value: 3 },
]);
smartInfoMock.searchFaces.mockResolvedValue(faces);
personMock.getFaceByIdWithAssets.mockResolvedValue(faceStub.noPerson1);
Expand All @@ -887,11 +905,14 @@ describe(PersonService.name, () => {
expect(personMock.reassignFaces).not.toHaveBeenCalled();
});

it('should not assign person to non-core face with no matching person', async () => {
const faces = [{ face: faceStub.noPerson1, distance: 0 }] as FaceSearchResult[];
it('should not assign person to deferred non-core face with no matching person', async () => {
const faces = [
{ face: faceStub.noPerson1, distance: 0 },
{ face: faceStub.noPerson2, distance: 0.4 },
] as FaceSearchResult[];

configMock.load.mockResolvedValue([
{ key: SystemConfigKey.MACHINE_LEARNING_FACIAL_RECOGNITION_MIN_FACES, value: 2 },
{ key: SystemConfigKey.MACHINE_LEARNING_FACIAL_RECOGNITION_MIN_FACES, value: 3 },
]);
smartInfoMock.searchFaces.mockResolvedValueOnce(faces).mockResolvedValueOnce([]);
personMock.getFaceByIdWithAssets.mockResolvedValue(faceStub.noPerson1);
Expand Down
10 changes: 8 additions & 2 deletions server/src/domain/person/person.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,13 @@ export class PersonService {
numResults: machineLearning.facialRecognition.minFaces,
});

this.logger.debug(`Face ${id} has ${matches.length} match${matches.length == 1 ? '' : 'es'}`);
// `matches` also includes the face itself
if (matches.length <= 1) {
this.logger.debug(`Face ${id} has no matches`);
return true;
}

this.logger.debug(`Face ${id} has ${matches.length} matches`);

const isCore = matches.length >= machineLearning.facialRecognition.minFaces;
if (!isCore && !deferred) {
Expand All @@ -426,7 +432,7 @@ export class PersonService {
return true;
}

let personId = matches.find((match) => match.face.personId)?.face.personId; // `matches` also includes the face itself
let personId = matches.find((match) => match.face.personId)?.face.personId;
if (!personId) {
const matchWithPerson = await this.smartInfoRepository.searchFaces({
userIds: [face.asset.ownerId],
Expand Down

0 comments on commit b31c768

Please sign in to comment.