mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 01:12:58 -04:00
feat: add job ids
This commit is contained in:
parent
c5360e78c5
commit
00ec2bd525
@ -144,7 +144,6 @@ export interface IAssetDeleteJob extends IEntityJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ILibraryFileJob extends IEntityJob {
|
export interface ILibraryFileJob extends IEntityJob {
|
||||||
ownerId: string;
|
|
||||||
assetPath: string;
|
assetPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +216,17 @@ export class JobRepository implements IJobRepository {
|
|||||||
|
|
||||||
private getJobOptions(item: JobItem): JobsOptions | null {
|
private getJobOptions(item: JobItem): JobsOptions | null {
|
||||||
switch (item.name) {
|
switch (item.name) {
|
||||||
|
case JobName.LIBRARY_QUEUE_SYNC_ASSETS:
|
||||||
|
case JobName.LIBRARY_QUEUE_SYNC_FILES:
|
||||||
|
case JobName.LIBRARY_SYNC_ASSET:
|
||||||
|
case JobName.LIBRARY_DELETE:
|
||||||
|
case JobName.SIDECAR_SYNC:
|
||||||
|
case JobName.SIDECAR_DISCOVERY: {
|
||||||
|
return { jobId: `${item.data.id}-${item.name}` };
|
||||||
|
}
|
||||||
|
case JobName.LIBRARY_SYNC_FILE: {
|
||||||
|
return { jobId: `${item.data.id}-${item.data.assetPath}` };
|
||||||
|
}
|
||||||
case JobName.NOTIFY_ALBUM_UPDATE: {
|
case JobName.NOTIFY_ALBUM_UPDATE: {
|
||||||
return { jobId: item.data.id, delay: item.data?.delay };
|
return { jobId: item.data.id, delay: item.data?.delay };
|
||||||
}
|
}
|
||||||
@ -228,6 +239,11 @@ export class JobRepository implements IJobRepository {
|
|||||||
case JobName.QUEUE_FACIAL_RECOGNITION: {
|
case JobName.QUEUE_FACIAL_RECOGNITION: {
|
||||||
return { jobId: JobName.QUEUE_FACIAL_RECOGNITION };
|
return { jobId: JobName.QUEUE_FACIAL_RECOGNITION };
|
||||||
}
|
}
|
||||||
|
case JobName.LIBRARY_QUEUE_SYNC_ALL:
|
||||||
|
case JobName.LIBRARY_QUEUE_CLEANUP: {
|
||||||
|
// These jobs are globally unique and should only have one instance running at a time
|
||||||
|
return { jobId: item.name };
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,6 @@ describe(LibraryService.name, () => {
|
|||||||
name: JobName.LIBRARY_SYNC_FILE,
|
name: JobName.LIBRARY_SYNC_FILE,
|
||||||
data: {
|
data: {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: libraryStub.externalLibrary1.owner.id,
|
|
||||||
assetPath: '/data/user1/photo.jpg',
|
assetPath: '/data/user1/photo.jpg',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -401,7 +400,6 @@ describe(LibraryService.name, () => {
|
|||||||
it('should import a new asset', async () => {
|
it('should import a new asset', async () => {
|
||||||
const mockLibraryJob: ILibraryFileJob = {
|
const mockLibraryJob: ILibraryFileJob = {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: mockUser.id,
|
|
||||||
assetPath: '/data/user1/photo.jpg',
|
assetPath: '/data/user1/photo.jpg',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -445,7 +443,6 @@ describe(LibraryService.name, () => {
|
|||||||
it('should import a new video', async () => {
|
it('should import a new video', async () => {
|
||||||
const mockLibraryJob: ILibraryFileJob = {
|
const mockLibraryJob: ILibraryFileJob = {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: mockUser.id,
|
|
||||||
assetPath: '/data/user1/video.mp4',
|
assetPath: '/data/user1/video.mp4',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -489,7 +486,6 @@ describe(LibraryService.name, () => {
|
|||||||
it('should not import an asset to a soft deleted library', async () => {
|
it('should not import an asset to a soft deleted library', async () => {
|
||||||
const mockLibraryJob: ILibraryFileJob = {
|
const mockLibraryJob: ILibraryFileJob = {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: mockUser.id,
|
|
||||||
assetPath: '/data/user1/photo.jpg',
|
assetPath: '/data/user1/photo.jpg',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -504,7 +500,6 @@ describe(LibraryService.name, () => {
|
|||||||
it('should not refresh a file whose mtime matches existing asset', async () => {
|
it('should not refresh a file whose mtime matches existing asset', async () => {
|
||||||
const mockLibraryJob: ILibraryFileJob = {
|
const mockLibraryJob: ILibraryFileJob = {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: mockUser.id,
|
|
||||||
assetPath: assetStub.hasFileExtension.originalPath,
|
assetPath: assetStub.hasFileExtension.originalPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -522,10 +517,9 @@ describe(LibraryService.name, () => {
|
|||||||
expect(jobMock.queueAll).not.toHaveBeenCalled();
|
expect(jobMock.queueAll).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should skip existing asset', async () => {
|
it('should skip an existing asset', async () => {
|
||||||
const mockLibraryJob: ILibraryFileJob = {
|
const mockLibraryJob: ILibraryFileJob = {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: mockUser.id,
|
|
||||||
assetPath: '/data/user1/photo.jpg',
|
assetPath: '/data/user1/photo.jpg',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -537,7 +531,6 @@ describe(LibraryService.name, () => {
|
|||||||
it('should not refresh an asset trashed by user', async () => {
|
it('should not refresh an asset trashed by user', async () => {
|
||||||
const mockLibraryJob: ILibraryFileJob = {
|
const mockLibraryJob: ILibraryFileJob = {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: mockUser.id,
|
|
||||||
assetPath: assetStub.hasFileExtension.originalPath,
|
assetPath: assetStub.hasFileExtension.originalPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -554,7 +547,6 @@ describe(LibraryService.name, () => {
|
|||||||
|
|
||||||
const mockLibraryJob: ILibraryFileJob = {
|
const mockLibraryJob: ILibraryFileJob = {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: userStub.admin.id,
|
|
||||||
assetPath: '/data/user1/photo.jpg',
|
assetPath: '/data/user1/photo.jpg',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -572,7 +564,6 @@ describe(LibraryService.name, () => {
|
|||||||
|
|
||||||
const mockLibraryJob: ILibraryFileJob = {
|
const mockLibraryJob: ILibraryFileJob = {
|
||||||
id: libraryStub.externalLibrary1.id,
|
id: libraryStub.externalLibrary1.id,
|
||||||
ownerId: userStub.admin.id,
|
|
||||||
assetPath: '/data/user1/photo.jpg',
|
assetPath: '/data/user1/photo.jpg',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -923,7 +914,6 @@ describe(LibraryService.name, () => {
|
|||||||
data: {
|
data: {
|
||||||
id: libraryStub.externalLibraryWithImportPaths1.id,
|
id: libraryStub.externalLibraryWithImportPaths1.id,
|
||||||
assetPath: '/foo/photo.jpg',
|
assetPath: '/foo/photo.jpg',
|
||||||
ownerId: libraryStub.externalLibraryWithImportPaths1.owner.id,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -948,7 +938,6 @@ describe(LibraryService.name, () => {
|
|||||||
data: {
|
data: {
|
||||||
id: libraryStub.externalLibraryWithImportPaths1.id,
|
id: libraryStub.externalLibraryWithImportPaths1.id,
|
||||||
assetPath: '/foo/photo.jpg',
|
assetPath: '/foo/photo.jpg',
|
||||||
ownerId: libraryStub.externalLibraryWithImportPaths1.owner.id,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -228,14 +228,13 @@ export class LibraryService extends BaseService {
|
|||||||
return mapLibrary(library);
|
return mapLibrary(library);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async syncFiles({ id, ownerId }: LibraryEntity, assetPaths: string[]) {
|
private async syncFiles({ id }: LibraryEntity, assetPaths: string[]) {
|
||||||
await this.jobRepository.queueAll(
|
await this.jobRepository.queueAll(
|
||||||
assetPaths.map((assetPath) => ({
|
assetPaths.map((assetPath) => ({
|
||||||
name: JobName.LIBRARY_SYNC_FILE,
|
name: JobName.LIBRARY_SYNC_FILE,
|
||||||
data: {
|
data: {
|
||||||
id,
|
id,
|
||||||
assetPath,
|
assetPath,
|
||||||
ownerId,
|
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
@ -401,7 +400,7 @@ export class LibraryService extends BaseService {
|
|||||||
const mtime = stat.mtime;
|
const mtime = stat.mtime;
|
||||||
|
|
||||||
asset = await this.assetRepository.create({
|
asset = await this.assetRepository.create({
|
||||||
ownerId: job.ownerId,
|
ownerId: library.ownerId,
|
||||||
libraryId: job.id,
|
libraryId: job.id,
|
||||||
checksum: pathHash,
|
checksum: pathHash,
|
||||||
originalPath: assetPath,
|
originalPath: assetPath,
|
||||||
@ -433,12 +432,18 @@ export class LibraryService extends BaseService {
|
|||||||
async queueScan(id: string) {
|
async queueScan(id: string) {
|
||||||
await this.findOrFail(id);
|
await this.findOrFail(id);
|
||||||
|
|
||||||
|
// We purge any existing scan jobs for this library. This is because the scan settings
|
||||||
|
// might have changed and the user wants to start a new scan with these settings.
|
||||||
|
await this.jobRepository.removeJob(id, JobName.LIBRARY_QUEUE_SYNC_FILES);
|
||||||
|
await this.jobRepository.removeJob(id, JobName.LIBRARY_QUEUE_SYNC_ASSETS);
|
||||||
|
|
||||||
await this.jobRepository.queue({
|
await this.jobRepository.queue({
|
||||||
name: JobName.LIBRARY_QUEUE_SYNC_FILES,
|
name: JobName.LIBRARY_QUEUE_SYNC_FILES,
|
||||||
data: {
|
data: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.jobRepository.queue({ name: JobName.LIBRARY_QUEUE_SYNC_ASSETS, data: { id } });
|
await this.jobRepository.queue({ name: JobName.LIBRARY_QUEUE_SYNC_ASSETS, data: { id } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user