refactor: enum casing (#19946)
This commit is contained in:
@@ -126,7 +126,7 @@ type Dates = {
|
||||
|
||||
@Injectable()
|
||||
export class MetadataService extends BaseService {
|
||||
@OnEvent({ name: 'AppBootstrap', workers: [ImmichWorker.MICROSERVICES] })
|
||||
@OnEvent({ name: 'AppBootstrap', workers: [ImmichWorker.Microservices] })
|
||||
async onBootstrap() {
|
||||
this.logger.log('Bootstrapping metadata service');
|
||||
await this.init();
|
||||
@@ -137,12 +137,12 @@ export class MetadataService extends BaseService {
|
||||
await this.metadataRepository.teardown();
|
||||
}
|
||||
|
||||
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.MICROSERVICES] })
|
||||
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.Microservices] })
|
||||
onConfigInit({ newConfig }: ArgOf<'ConfigInit'>) {
|
||||
this.metadataRepository.setMaxConcurrency(newConfig.job.metadataExtraction.concurrency);
|
||||
}
|
||||
|
||||
@OnEvent({ name: 'ConfigUpdate', workers: [ImmichWorker.MICROSERVICES], server: true })
|
||||
@OnEvent({ name: 'ConfigUpdate', workers: [ImmichWorker.Microservices], server: true })
|
||||
onConfigUpdate({ newConfig }: ArgOf<'ConfigUpdate'>) {
|
||||
this.metadataRepository.setMaxConcurrency(newConfig.job.metadataExtraction.concurrency);
|
||||
}
|
||||
@@ -151,9 +151,9 @@ export class MetadataService extends BaseService {
|
||||
this.logger.log('Initializing metadata service');
|
||||
|
||||
try {
|
||||
await this.jobRepository.pause(QueueName.METADATA_EXTRACTION);
|
||||
await this.jobRepository.pause(QueueName.MetadataExtraction);
|
||||
await this.databaseRepository.withLock(DatabaseLock.GeodataImport, () => this.mapRepository.init());
|
||||
await this.jobRepository.resume(QueueName.METADATA_EXTRACTION);
|
||||
await this.jobRepository.resume(QueueName.MetadataExtraction);
|
||||
|
||||
this.logger.log(`Initialized local reverse geocoder`);
|
||||
} catch (error: Error | any) {
|
||||
@@ -170,7 +170,7 @@ export class MetadataService extends BaseService {
|
||||
return;
|
||||
}
|
||||
|
||||
const otherType = asset.type === AssetType.VIDEO ? AssetType.IMAGE : AssetType.VIDEO;
|
||||
const otherType = asset.type === AssetType.Video ? AssetType.Image : AssetType.Video;
|
||||
const match = await this.assetRepository.findLivePhotoMatch({
|
||||
livePhotoCID: exifInfo.livePhotoCID,
|
||||
ownerId: asset.ownerId,
|
||||
@@ -183,23 +183,23 @@ export class MetadataService extends BaseService {
|
||||
return;
|
||||
}
|
||||
|
||||
const [photoAsset, motionAsset] = asset.type === AssetType.IMAGE ? [asset, match] : [match, asset];
|
||||
const [photoAsset, motionAsset] = asset.type === AssetType.Image ? [asset, match] : [match, asset];
|
||||
await Promise.all([
|
||||
this.assetRepository.update({ id: photoAsset.id, livePhotoVideoId: motionAsset.id }),
|
||||
this.assetRepository.update({ id: motionAsset.id, visibility: AssetVisibility.HIDDEN }),
|
||||
this.assetRepository.update({ id: motionAsset.id, visibility: AssetVisibility.Hidden }),
|
||||
this.albumRepository.removeAssetsFromAll([motionAsset.id]),
|
||||
]);
|
||||
|
||||
await this.eventRepository.emit('AssetHide', { assetId: motionAsset.id, userId: motionAsset.ownerId });
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.QUEUE_METADATA_EXTRACTION, queue: QueueName.METADATA_EXTRACTION })
|
||||
async handleQueueMetadataExtraction(job: JobOf<JobName.QUEUE_METADATA_EXTRACTION>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.QueueMetadataExtraction, queue: QueueName.MetadataExtraction })
|
||||
async handleQueueMetadataExtraction(job: JobOf<JobName.QueueMetadataExtraction>): Promise<JobStatus> {
|
||||
const { force } = job;
|
||||
|
||||
let queue: { name: JobName.METADATA_EXTRACTION; data: { id: string } }[] = [];
|
||||
let queue: { name: JobName.MetadataExtraction; data: { id: string } }[] = [];
|
||||
for await (const asset of this.assetJobRepository.streamForMetadataExtraction(force)) {
|
||||
queue.push({ name: JobName.METADATA_EXTRACTION, data: { id: asset.id } });
|
||||
queue.push({ name: JobName.MetadataExtraction, data: { id: asset.id } });
|
||||
|
||||
if (queue.length >= JOBS_ASSET_PAGINATION_SIZE) {
|
||||
await this.jobRepository.queueAll(queue);
|
||||
@@ -208,11 +208,11 @@ export class MetadataService extends BaseService {
|
||||
}
|
||||
|
||||
await this.jobRepository.queueAll(queue);
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.METADATA_EXTRACTION, queue: QueueName.METADATA_EXTRACTION })
|
||||
async handleMetadataExtraction(data: JobOf<JobName.METADATA_EXTRACTION>) {
|
||||
@OnJob({ name: JobName.MetadataExtraction, queue: QueueName.MetadataExtraction })
|
||||
async handleMetadataExtraction(data: JobOf<JobName.MetadataExtraction>) {
|
||||
const [{ metadata, reverseGeocoding }, asset] = await Promise.all([
|
||||
this.getConfig({ withCache: true }),
|
||||
this.assetJobRepository.getForMetadataExtraction(data.id),
|
||||
@@ -320,8 +320,8 @@ export class MetadataService extends BaseService {
|
||||
});
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.QUEUE_SIDECAR, queue: QueueName.SIDECAR })
|
||||
async handleQueueSidecar({ force }: JobOf<JobName.QUEUE_SIDECAR>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.QueueSidecar, queue: QueueName.Sidecar })
|
||||
async handleQueueSidecar({ force }: JobOf<JobName.QueueSidecar>): Promise<JobStatus> {
|
||||
let jobs: JobItem[] = [];
|
||||
const queueAll = async () => {
|
||||
await this.jobRepository.queueAll(jobs);
|
||||
@@ -330,7 +330,7 @@ export class MetadataService extends BaseService {
|
||||
|
||||
const assets = this.assetJobRepository.streamForSidecar(force);
|
||||
for await (const asset of assets) {
|
||||
jobs.push({ name: force ? JobName.SIDECAR_SYNC : JobName.SIDECAR_DISCOVERY, data: { id: asset.id } });
|
||||
jobs.push({ name: force ? JobName.SidecarSync : JobName.SidecarDiscovery, data: { id: asset.id } });
|
||||
if (jobs.length >= JOBS_ASSET_PAGINATION_SIZE) {
|
||||
await queueAll();
|
||||
}
|
||||
@@ -338,35 +338,35 @@ export class MetadataService extends BaseService {
|
||||
|
||||
await queueAll();
|
||||
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.SIDECAR_SYNC, queue: QueueName.SIDECAR })
|
||||
handleSidecarSync({ id }: JobOf<JobName.SIDECAR_SYNC>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.SidecarSync, queue: QueueName.Sidecar })
|
||||
handleSidecarSync({ id }: JobOf<JobName.SidecarSync>): Promise<JobStatus> {
|
||||
return this.processSidecar(id, true);
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.SIDECAR_DISCOVERY, queue: QueueName.SIDECAR })
|
||||
handleSidecarDiscovery({ id }: JobOf<JobName.SIDECAR_DISCOVERY>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.SidecarDiscovery, queue: QueueName.Sidecar })
|
||||
handleSidecarDiscovery({ id }: JobOf<JobName.SidecarDiscovery>): Promise<JobStatus> {
|
||||
return this.processSidecar(id, false);
|
||||
}
|
||||
|
||||
@OnEvent({ name: 'AssetTag' })
|
||||
async handleTagAsset({ assetId }: ArgOf<'AssetTag'>) {
|
||||
await this.jobRepository.queue({ name: JobName.SIDECAR_WRITE, data: { id: assetId, tags: true } });
|
||||
await this.jobRepository.queue({ name: JobName.SidecarWrite, data: { id: assetId, tags: true } });
|
||||
}
|
||||
|
||||
@OnEvent({ name: 'AssetUntag' })
|
||||
async handleUntagAsset({ assetId }: ArgOf<'AssetUntag'>) {
|
||||
await this.jobRepository.queue({ name: JobName.SIDECAR_WRITE, data: { id: assetId, tags: true } });
|
||||
await this.jobRepository.queue({ name: JobName.SidecarWrite, data: { id: assetId, tags: true } });
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.SIDECAR_WRITE, queue: QueueName.SIDECAR })
|
||||
async handleSidecarWrite(job: JobOf<JobName.SIDECAR_WRITE>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.SidecarWrite, queue: QueueName.Sidecar })
|
||||
async handleSidecarWrite(job: JobOf<JobName.SidecarWrite>): Promise<JobStatus> {
|
||||
const { id, description, dateTimeOriginal, latitude, longitude, rating, tags } = job;
|
||||
const asset = await this.assetJobRepository.getForSidecarWriteJob(id);
|
||||
if (!asset) {
|
||||
return JobStatus.FAILED;
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
const tagsList = (asset.tags || []).map((tag) => tag.value);
|
||||
@@ -386,7 +386,7 @@ export class MetadataService extends BaseService {
|
||||
);
|
||||
|
||||
if (Object.keys(exif).length === 0) {
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
await this.metadataRepository.writeTags(sidecarPath, exif);
|
||||
@@ -395,7 +395,7 @@ export class MetadataService extends BaseService {
|
||||
await this.assetRepository.update({ id, sidecarPath });
|
||||
}
|
||||
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
private getImageDimensions(exifTags: ImmichTags): { width?: number; height?: number } {
|
||||
@@ -416,7 +416,7 @@ export class MetadataService extends BaseService {
|
||||
sidecarPath: string | null;
|
||||
type: AssetType;
|
||||
}): Promise<ImmichTags> {
|
||||
if (!asset.sidecarPath && asset.type === AssetType.IMAGE) {
|
||||
if (!asset.sidecarPath && asset.type === AssetType.Image) {
|
||||
return this.metadataRepository.readTags(asset.originalPath);
|
||||
}
|
||||
|
||||
@@ -431,7 +431,7 @@ export class MetadataService extends BaseService {
|
||||
const [mediaTags, sidecarTags, videoTags] = await Promise.all([
|
||||
this.metadataRepository.readTags(asset.originalPath),
|
||||
asset.sidecarPath ? this.metadataRepository.readTags(asset.sidecarPath) : null,
|
||||
asset.type === AssetType.VIDEO ? this.getVideoTags(asset.originalPath) : null,
|
||||
asset.type === AssetType.Video ? this.getVideoTags(asset.originalPath) : null,
|
||||
]);
|
||||
|
||||
// prefer dates from sidecar tags
|
||||
@@ -488,7 +488,7 @@ export class MetadataService extends BaseService {
|
||||
}
|
||||
|
||||
private isMotionPhoto(asset: { type: AssetType }, tags: ImmichTags): boolean {
|
||||
return asset.type === AssetType.IMAGE && !!(tags.MotionPhoto || tags.MicroVideo);
|
||||
return asset.type === AssetType.Image && !!(tags.MotionPhoto || tags.MicroVideo);
|
||||
}
|
||||
|
||||
private async applyMotionPhotos(asset: Asset, tags: ImmichTags, dates: Dates, stats: Stats) {
|
||||
@@ -558,10 +558,10 @@ export class MetadataService extends BaseService {
|
||||
});
|
||||
|
||||
// Hide the motion photo video asset if it's not already hidden to prepare for linking
|
||||
if (motionAsset.visibility === AssetVisibility.TIMELINE) {
|
||||
if (motionAsset.visibility === AssetVisibility.Timeline) {
|
||||
await this.assetRepository.update({
|
||||
id: motionAsset.id,
|
||||
visibility: AssetVisibility.HIDDEN,
|
||||
visibility: AssetVisibility.Hidden,
|
||||
});
|
||||
this.logger.log(`Hid unlinked motion photo video asset (${motionAsset.id})`);
|
||||
}
|
||||
@@ -570,7 +570,7 @@ export class MetadataService extends BaseService {
|
||||
motionAsset = await this.assetRepository.create({
|
||||
id: motionAssetId,
|
||||
libraryId: asset.libraryId,
|
||||
type: AssetType.VIDEO,
|
||||
type: AssetType.Video,
|
||||
fileCreatedAt: dates.dateTimeOriginal,
|
||||
fileModifiedAt: stats.mtime,
|
||||
localDateTime: dates.localDateTime,
|
||||
@@ -578,7 +578,7 @@ export class MetadataService extends BaseService {
|
||||
ownerId: asset.ownerId,
|
||||
originalPath: StorageCore.getAndroidMotionPath(asset, motionAssetId),
|
||||
originalFileName: `${path.parse(asset.originalFileName).name}.mp4`,
|
||||
visibility: AssetVisibility.HIDDEN,
|
||||
visibility: AssetVisibility.Hidden,
|
||||
deviceAssetId: 'NONE',
|
||||
deviceId: 'NONE',
|
||||
});
|
||||
@@ -597,7 +597,7 @@ export class MetadataService extends BaseService {
|
||||
// note asset.livePhotoVideoId is not motionAsset.id yet
|
||||
if (asset.livePhotoVideoId) {
|
||||
await this.jobRepository.queue({
|
||||
name: JobName.ASSET_DELETION,
|
||||
name: JobName.AssetDeletion,
|
||||
data: { id: asset.livePhotoVideoId, deleteOnDisk: true },
|
||||
});
|
||||
this.logger.log(`Removed old motion photo video asset (${asset.livePhotoVideoId})`);
|
||||
@@ -612,7 +612,7 @@ export class MetadataService extends BaseService {
|
||||
this.logger.log(`Wrote motion photo video to ${motionAsset.originalPath}`);
|
||||
|
||||
await this.handleMetadataExtraction({ id: motionAsset.id });
|
||||
await this.jobRepository.queue({ name: JobName.VIDEO_CONVERSION, data: { id: motionAsset.id } });
|
||||
await this.jobRepository.queue({ name: JobName.VideoConversation, data: { id: motionAsset.id } });
|
||||
}
|
||||
|
||||
this.logger.debug(`Finished motion photo video extraction for asset ${asset.id}: ${asset.originalPath}`);
|
||||
@@ -740,7 +740,7 @@ export class MetadataService extends BaseService {
|
||||
boundingBoxY1: Math.floor((region.Area.Y - region.Area.H / 2) * imageHeight),
|
||||
boundingBoxX2: Math.floor((region.Area.X + region.Area.W / 2) * imageWidth),
|
||||
boundingBoxY2: Math.floor((region.Area.Y + region.Area.H / 2) * imageHeight),
|
||||
sourceType: SourceType.EXIF,
|
||||
sourceType: SourceType.Exif,
|
||||
};
|
||||
|
||||
facesToAdd.push(face);
|
||||
@@ -753,11 +753,11 @@ export class MetadataService extends BaseService {
|
||||
if (missing.length > 0) {
|
||||
this.logger.debugFn(() => `Creating missing persons: ${missing.map((p) => `${p.name}/${p.id}`)}`);
|
||||
const newPersonIds = await this.personRepository.createAll(missing);
|
||||
const jobs = newPersonIds.map((id) => ({ name: JobName.GENERATE_PERSON_THUMBNAIL, data: { id } }) as const);
|
||||
const jobs = newPersonIds.map((id) => ({ name: JobName.GeneratePersonThumbnail, data: { id } }) as const);
|
||||
await this.jobRepository.queueAll(jobs);
|
||||
}
|
||||
|
||||
const facesToRemove = asset.faces.filter((face) => face.sourceType === SourceType.EXIF).map((face) => face.id);
|
||||
const facesToRemove = asset.faces.filter((face) => face.sourceType === SourceType.Exif).map((face) => face.id);
|
||||
if (facesToRemove.length > 0) {
|
||||
this.logger.debug(`Removing ${facesToRemove.length} faces for asset ${asset.id}: ${asset.originalPath}`);
|
||||
}
|
||||
@@ -894,15 +894,15 @@ export class MetadataService extends BaseService {
|
||||
const [asset] = await this.assetRepository.getByIds([id]);
|
||||
|
||||
if (!asset) {
|
||||
return JobStatus.FAILED;
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
if (isSync && !asset.sidecarPath) {
|
||||
return JobStatus.FAILED;
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
if (!isSync && (asset.visibility === AssetVisibility.HIDDEN || asset.sidecarPath) && !asset.isExternal) {
|
||||
return JobStatus.FAILED;
|
||||
if (!isSync && (asset.visibility === AssetVisibility.Hidden || asset.sidecarPath) && !asset.isExternal) {
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
// XMP sidecars can come in two filename formats. For a photo named photo.ext, the filenames are photo.ext.xmp and photo.xmp
|
||||
@@ -927,22 +927,22 @@ export class MetadataService extends BaseService {
|
||||
if (sidecarPath !== asset.sidecarPath) {
|
||||
await this.assetRepository.update({ id: asset.id, sidecarPath });
|
||||
}
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
if (sidecarPath) {
|
||||
this.logger.debug(`Detected sidecar at '${sidecarPath}' for asset ${asset.id}: ${asset.originalPath}`);
|
||||
await this.assetRepository.update({ id: asset.id, sidecarPath });
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
if (!isSync) {
|
||||
return JobStatus.FAILED;
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
this.logger.debug(`No sidecar found for asset ${asset.id}: ${asset.originalPath}`);
|
||||
await this.assetRepository.update({ id: asset.id, sidecarPath: null });
|
||||
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user