diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index f850ac74bc..4017a8024e 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -5024,6 +5024,9 @@ "sidecar": { "$ref": "#/components/schemas/JobStatusDto" }, + "smartAlbum": { + "$ref": "#/components/schemas/JobStatusDto" + }, "storageTemplateMigration": { "$ref": "#/components/schemas/JobStatusDto" }, @@ -5044,7 +5047,8 @@ "backgroundTask", "search", "recognizeFaces", - "sidecar" + "sidecar", + "smartAlbum" ], "type": "object" }, @@ -6344,7 +6348,8 @@ "backgroundTask", "storageTemplateMigration", "search", - "sidecar" + "sidecar", + "smartAlbum" ], "type": "string" }, @@ -7478,6 +7483,9 @@ "sidecar": { "$ref": "#/components/schemas/JobSettingsDto" }, + "smartAlbum": { + "$ref": "#/components/schemas/JobSettingsDto" + }, "storageTemplateMigration": { "$ref": "#/components/schemas/JobSettingsDto" }, @@ -7498,7 +7506,8 @@ "backgroundTask", "search", "recognizeFaces", - "sidecar" + "sidecar", + "smartAlbum" ], "type": "object" }, diff --git a/server/src/domain/job/job.constants.ts b/server/src/domain/job/job.constants.ts index a02248b306..03b4781777 100644 --- a/server/src/domain/job/job.constants.ts +++ b/server/src/domain/job/job.constants.ts @@ -9,6 +9,7 @@ export enum QueueName { STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration', SEARCH = 'search', SIDECAR = 'sidecar', + SMART_ALBUM = 'smartAlbum', } export enum JobCommand { @@ -74,6 +75,10 @@ export enum JobName { QUEUE_SIDECAR = 'queue-sidecar', SIDECAR_DISCOVERY = 'sidecar-discovery', SIDECAR_SYNC = 'sidecar-sync', + + // smart albums + SMART_ALBUM_INDEX = 'smart-album-index', + SMART_ALBUM_INSERT = 'smart-album-insert', } export const JOBS_ASSET_PAGINATION_SIZE = 1000; @@ -136,4 +141,8 @@ export const JOBS_TO_QUEUE: Record = { [JobName.QUEUE_SIDECAR]: QueueName.SIDECAR, [JobName.SIDECAR_DISCOVERY]: QueueName.SIDECAR, [JobName.SIDECAR_SYNC]: QueueName.SIDECAR, + + // smart albums + [JobName.SMART_ALBUM_INDEX]: QueueName.SMART_ALBUM, + [JobName.SMART_ALBUM_INSERT]: QueueName.SMART_ALBUM, }; diff --git a/server/src/domain/job/job.dto.ts b/server/src/domain/job/job.dto.ts index 1c59409567..15e38544d6 100644 --- a/server/src/domain/job/job.dto.ts +++ b/server/src/domain/job/job.dto.ts @@ -78,4 +78,7 @@ export class AllJobStatusResponseDto implements Record @ApiProperty({ type: JobStatusDto }) [QueueName.SIDECAR]!: JobStatusDto; + + @ApiProperty({ type: JobStatusDto }) + [QueueName.SMART_ALBUM]!: JobStatusDto; } diff --git a/server/src/domain/job/job.interface.ts b/server/src/domain/job/job.interface.ts index 176b2942af..4f3ed64b66 100644 --- a/server/src/domain/job/job.interface.ts +++ b/server/src/domain/job/job.interface.ts @@ -29,3 +29,13 @@ export interface IBulkEntityJob extends IBaseJob { export interface IDeleteFilesJob extends IBaseJob { files: Array; } + +export interface ISmartAlbumIndexJob extends IBaseJob { + albumId: string; + ruleId: string; +} + +export interface ISmartAlbumInsertJob extends IBaseJob { + albumId: string; + assetId: string; +} diff --git a/server/src/domain/job/job.repository.ts b/server/src/domain/job/job.repository.ts index c088a2eedf..639d1db8e6 100644 --- a/server/src/domain/job/job.repository.ts +++ b/server/src/domain/job/job.repository.ts @@ -6,6 +6,8 @@ import { IDeleteFilesJob, IEntityJob, IFaceThumbnailJob, + ISmartAlbumIndexJob, + ISmartAlbumInsertJob, } from './job.interface'; export interface JobCounts { @@ -79,7 +81,11 @@ export type JobItem = | { name: JobName.SEARCH_INDEX_ALBUM; data: IBulkEntityJob } | { name: JobName.SEARCH_REMOVE_ASSET; data: IBulkEntityJob } | { name: JobName.SEARCH_REMOVE_ALBUM; data: IBulkEntityJob } - | { name: JobName.SEARCH_REMOVE_FACE; data: IAssetFaceJob }; + | { name: JobName.SEARCH_REMOVE_FACE; data: IAssetFaceJob } + + // Smart album + | { name: JobName.SMART_ALBUM_INDEX; data: ISmartAlbumIndexJob } + | { name: JobName.SMART_ALBUM_INSERT; data: ISmartAlbumInsertJob }; export type JobHandler = (data: T) => boolean | Promise; diff --git a/server/src/domain/system-config/dto/system-config-job.dto.ts b/server/src/domain/system-config/dto/system-config-job.dto.ts index ce9bcb7e77..3b6cf1a2ae 100644 --- a/server/src/domain/system-config/dto/system-config-job.dto.ts +++ b/server/src/domain/system-config/dto/system-config-job.dto.ts @@ -70,4 +70,10 @@ export class SystemConfigJobDto implements Record { @IsObject() @Type(() => JobSettingsDto) [QueueName.SIDECAR]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.SMART_ALBUM]!: JobSettingsDto; } diff --git a/server/src/domain/system-config/system-config.core.ts b/server/src/domain/system-config/system-config.core.ts index 80f650571c..6f7724705c 100644 --- a/server/src/domain/system-config/system-config.core.ts +++ b/server/src/domain/system-config/system-config.core.ts @@ -43,6 +43,7 @@ export const defaults = Object.freeze({ [QueueName.STORAGE_TEMPLATE_MIGRATION]: { concurrency: 5 }, [QueueName.THUMBNAIL_GENERATION]: { concurrency: 5 }, [QueueName.VIDEO_CONVERSION]: { concurrency: 1 }, + [QueueName.SMART_ALBUM]: { concurrency: 1 }, }, oauth: { enabled: false, diff --git a/server/src/microservices/app.service.ts b/server/src/microservices/app.service.ts index a8f30e1888..86af8f5d63 100644 --- a/server/src/microservices/app.service.ts +++ b/server/src/microservices/app.service.ts @@ -73,6 +73,12 @@ export class AppService { [JobName.QUEUE_SIDECAR]: (data) => this.metadataService.handleQueueSidecar(data), [JobName.SIDECAR_DISCOVERY]: (data) => this.metadataService.handleSidecarDiscovery(data), [JobName.SIDECAR_SYNC]: () => this.metadataService.handleSidecarSync(), + [JobName.SMART_ALBUM_INDEX]: (data) => { + throw new Error('Not implemented SMART_ALBUM_INDEX'); + }, + [JobName.SMART_ALBUM_INSERT]: (data) => { + throw new Error('Not implemented SMART_ALBUM_INSERT'); + }, }); process.on('uncaughtException', (error: Error | any) => {