mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:17:11 -05:00 
			
		
		
		
	feat(server): optimize face re-queueing (#6961)
* do not defer faces with no matches * move comment
This commit is contained in:
		
							parent
							
								
									479fca8f02
								
							
						
					
					
						commit
						b31c7681ae
					
				@ -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);
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
@ -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],
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user