mirror of
https://github.com/immich-app/immich.git
synced 2025-07-09 03:04:16 -04:00
feat(server): set exiftool process count (#16388)
exiftool concurrency control
This commit is contained in:
parent
fb907d707d
commit
6050485ad8
@ -85,6 +85,10 @@ export class MetadataRepository {
|
|||||||
this.logger.setContext(MetadataRepository.name);
|
this.logger.setContext(MetadataRepository.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMaxConcurrency(concurrency: number) {
|
||||||
|
this.exiftool.batchCluster.setMaxProcs(concurrency);
|
||||||
|
}
|
||||||
|
|
||||||
async teardown() {
|
async teardown() {
|
||||||
await this.exiftool.end();
|
await this.exiftool.end();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { BinaryField, ExifDateTime } from 'exiftool-vendored';
|
|||||||
import { randomBytes } from 'node:crypto';
|
import { randomBytes } from 'node:crypto';
|
||||||
import { Stats } from 'node:fs';
|
import { Stats } from 'node:fs';
|
||||||
import { constants } from 'node:fs/promises';
|
import { constants } from 'node:fs/promises';
|
||||||
|
import { defaults } from 'src/config';
|
||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { ExifEntity } from 'src/entities/exif.entity';
|
import { ExifEntity } from 'src/entities/exif.entity';
|
||||||
import { AssetType, ExifOrientation, ImmichWorker, JobName, JobStatus, SourceType } from 'src/enum';
|
import { AssetType, ExifOrientation, ImmichWorker, JobName, JobStatus, SourceType } from 'src/enum';
|
||||||
@ -54,6 +55,27 @@ describe(MetadataService.name, () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('onConfigInit', () => {
|
||||||
|
it('should update metadata processing concurrency', () => {
|
||||||
|
sut.onConfigInit({ newConfig: defaults });
|
||||||
|
|
||||||
|
expect(mocks.metadata.setMaxConcurrency).toHaveBeenCalledWith(defaults.job.metadataExtraction.concurrency);
|
||||||
|
expect(mocks.metadata.setMaxConcurrency).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onConfigUpdate', () => {
|
||||||
|
it('should update metadata processing concurrency', () => {
|
||||||
|
const newConfig = structuredClone(defaults);
|
||||||
|
newConfig.job.metadataExtraction.concurrency = 10;
|
||||||
|
|
||||||
|
sut.onConfigUpdate({ oldConfig: defaults, newConfig });
|
||||||
|
|
||||||
|
expect(mocks.metadata.setMaxConcurrency).toHaveBeenCalledWith(newConfig.job.metadataExtraction.concurrency);
|
||||||
|
expect(mocks.metadata.setMaxConcurrency).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('handleLivePhotoLinking', () => {
|
describe('handleLivePhotoLinking', () => {
|
||||||
it('should handle an asset that could not be found', async () => {
|
it('should handle an asset that could not be found', async () => {
|
||||||
await expect(sut.handleLivePhotoLinking({ id: assetStub.image.id })).resolves.toBe(JobStatus.FAILED);
|
await expect(sut.handleLivePhotoLinking({ id: assetStub.image.id })).resolves.toBe(JobStatus.FAILED);
|
||||||
|
@ -89,6 +89,16 @@ export class MetadataService extends BaseService {
|
|||||||
await this.metadataRepository.teardown();
|
await this.metadataRepository.teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] })
|
||||||
|
onConfigInit({ newConfig }: ArgOf<'config.init'>) {
|
||||||
|
this.metadataRepository.setMaxConcurrency(newConfig.job.metadataExtraction.concurrency);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnEvent({ name: 'config.update', workers: [ImmichWorker.MICROSERVICES], server: true })
|
||||||
|
onConfigUpdate({ newConfig }: ArgOf<'config.update'>) {
|
||||||
|
this.metadataRepository.setMaxConcurrency(newConfig.job.metadataExtraction.concurrency);
|
||||||
|
}
|
||||||
|
|
||||||
private async init() {
|
private async init() {
|
||||||
this.logger.log('Initializing metadata service');
|
this.logger.log('Initializing metadata service');
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { Mocked, vitest } from 'vitest';
|
|||||||
|
|
||||||
export const newMetadataRepositoryMock = (): Mocked<RepositoryInterface<MetadataRepository>> => {
|
export const newMetadataRepositoryMock = (): Mocked<RepositoryInterface<MetadataRepository>> => {
|
||||||
return {
|
return {
|
||||||
|
setMaxConcurrency: vitest.fn(),
|
||||||
teardown: vitest.fn(),
|
teardown: vitest.fn(),
|
||||||
readTags: vitest.fn(),
|
readTags: vitest.fn(),
|
||||||
writeTags: vitest.fn(),
|
writeTags: vitest.fn(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user