mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
refactor(server): job repository (#1382)
* refactor(server): job repository * refactor: job repository * chore: generate open-api * fix: job panel * Remove incorrect subtitle Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
@@ -8,203 +8,97 @@
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import JobTile from './job-tile.svelte';
|
||||
|
||||
let allJobsStatus: AllJobStatusResponseDto;
|
||||
let setIntervalHandler: NodeJS.Timer;
|
||||
let jobs: AllJobStatusResponseDto;
|
||||
let timer: NodeJS.Timer;
|
||||
|
||||
const load = async () => {
|
||||
const { data } = await api.jobApi.getAllJobsStatus();
|
||||
jobs = data;
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
const { data } = await api.jobApi.getAllJobsStatus();
|
||||
allJobsStatus = data;
|
||||
|
||||
setIntervalHandler = setInterval(async () => {
|
||||
const { data } = await api.jobApi.getAllJobsStatus();
|
||||
allJobsStatus = data;
|
||||
}, 1000);
|
||||
await load();
|
||||
timer = setInterval(async () => await load(), 5_000);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(setIntervalHandler);
|
||||
clearInterval(timer);
|
||||
});
|
||||
|
||||
const runThumbnailGeneration = async () => {
|
||||
const run = async (jobId: JobId, jobName: string, emptyMessage: string) => {
|
||||
try {
|
||||
const { data } = await api.jobApi.sendJobCommand(JobId.ThumbnailGeneration, {
|
||||
command: JobCommand.Start
|
||||
});
|
||||
const { data } = await api.jobApi.sendJobCommand(jobId, { command: JobCommand.Start });
|
||||
|
||||
if (data) {
|
||||
notificationController.show({
|
||||
message: `Thumbnail generation job started for ${data} assets`,
|
||||
message: `Started ${jobName}`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
} else {
|
||||
notificationController.show({
|
||||
message: `No missing thumbnails found`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[ERROR] runThumbnailGeneration', e);
|
||||
|
||||
notificationController.show({
|
||||
message: `Error running thumbnail generation job, check console for more detail`,
|
||||
type: NotificationType.Error
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const runExtractEXIF = async () => {
|
||||
try {
|
||||
const { data } = await api.jobApi.sendJobCommand(JobId.MetadataExtraction, {
|
||||
command: JobCommand.Start
|
||||
});
|
||||
|
||||
if (data) {
|
||||
notificationController.show({
|
||||
message: `Extract EXIF job started for ${data} assets`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
} else {
|
||||
notificationController.show({
|
||||
message: `No missing EXIF found`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[ERROR] runExtractEXIF', e);
|
||||
|
||||
notificationController.show({
|
||||
message: `Error running extract EXIF job, check console for more detail`,
|
||||
type: NotificationType.Error
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const runMachineLearning = async () => {
|
||||
try {
|
||||
const { data } = await api.jobApi.sendJobCommand(JobId.MachineLearning, {
|
||||
command: JobCommand.Start
|
||||
});
|
||||
|
||||
if (data) {
|
||||
notificationController.show({
|
||||
message: `Object detection job started for ${data} assets`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
} else {
|
||||
notificationController.show({
|
||||
message: `No missing object detection found`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
notificationController.show({ message: emptyMessage, type: NotificationType.Info });
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error, `Error running machine learning job, check console for more detail`);
|
||||
}
|
||||
};
|
||||
|
||||
const runVideoConversion = async () => {
|
||||
try {
|
||||
const { data } = await api.jobApi.sendJobCommand(JobId.VideoConversion, {
|
||||
command: JobCommand.Start
|
||||
});
|
||||
|
||||
if (data) {
|
||||
notificationController.show({
|
||||
message: `Video conversion job started for ${data} assets`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
} else {
|
||||
notificationController.show({
|
||||
message: `No videos without an encoded version found`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error, `Error running video conversion job, check console for more detail`);
|
||||
}
|
||||
};
|
||||
|
||||
const runTemplateMigration = async () => {
|
||||
try {
|
||||
const { data } = await api.jobApi.sendJobCommand(JobId.StorageTemplateMigration, {
|
||||
command: JobCommand.Start
|
||||
});
|
||||
|
||||
if (data) {
|
||||
notificationController.show({
|
||||
message: `Storage migration started`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
} else {
|
||||
notificationController.show({
|
||||
message: `All files have been migrated to the new storage template`,
|
||||
type: NotificationType.Info
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[ERROR] runTemplateMigration', e);
|
||||
|
||||
notificationController.show({
|
||||
message: `Error running template migration job, check console for more detail`,
|
||||
type: NotificationType.Error
|
||||
});
|
||||
handleError(error, `Unable to start ${jobName}`);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-10">
|
||||
<JobTile
|
||||
title={'Generate thumbnails'}
|
||||
subtitle={'Regenerate missing thumbnail (JPEG, WEBP)'}
|
||||
on:click={runThumbnailGeneration}
|
||||
jobStatus={allJobsStatus?.isThumbnailGenerationActive}
|
||||
waitingJobCount={allJobsStatus?.thumbnailGenerationQueueCount.waiting}
|
||||
activeJobCount={allJobsStatus?.thumbnailGenerationQueueCount.active}
|
||||
/>
|
||||
{#if jobs}
|
||||
<JobTile
|
||||
title={'Generate thumbnails'}
|
||||
subtitle={'Regenerate missing thumbnail (JPEG, WEBP)'}
|
||||
on:click={() =>
|
||||
run(JobId.ThumbnailGeneration, 'thumbnail generation', 'No missing thumbnails found')}
|
||||
jobCounts={jobs[JobId.ThumbnailGeneration]}
|
||||
/>
|
||||
|
||||
<JobTile
|
||||
title={'Extract EXIF'}
|
||||
subtitle={'Extract missing EXIF information'}
|
||||
on:click={runExtractEXIF}
|
||||
jobStatus={allJobsStatus?.isMetadataExtractionActive}
|
||||
waitingJobCount={allJobsStatus?.metadataExtractionQueueCount.waiting}
|
||||
activeJobCount={allJobsStatus?.metadataExtractionQueueCount.active}
|
||||
/>
|
||||
<JobTile
|
||||
title={'Extract EXIF'}
|
||||
subtitle={'Extract missing EXIF information'}
|
||||
on:click={() => run(JobId.MetadataExtraction, 'extract EXIF', 'No missing EXIF found')}
|
||||
jobCounts={jobs[JobId.MetadataExtraction]}
|
||||
/>
|
||||
|
||||
<JobTile
|
||||
title={'Detect objects'}
|
||||
subtitle={'Run machine learning process to detect and classify objects'}
|
||||
on:click={runMachineLearning}
|
||||
jobStatus={allJobsStatus?.isMachineLearningActive}
|
||||
waitingJobCount={allJobsStatus?.machineLearningQueueCount.waiting}
|
||||
activeJobCount={allJobsStatus?.machineLearningQueueCount.active}
|
||||
>
|
||||
Note that some assets may not have any objects detected, this is normal.
|
||||
</JobTile>
|
||||
|
||||
<JobTile
|
||||
title={'Video transcoding'}
|
||||
subtitle={'Run video transcoding process to transcode videos not in the desired format'}
|
||||
on:click={runVideoConversion}
|
||||
jobStatus={allJobsStatus?.isVideoConversionActive}
|
||||
waitingJobCount={allJobsStatus?.videoConversionQueueCount.waiting}
|
||||
activeJobCount={allJobsStatus?.videoConversionQueueCount.active}
|
||||
>
|
||||
Note that some videos won't require transcoding, this is normal.
|
||||
</JobTile>
|
||||
|
||||
<JobTile
|
||||
title={'Storage migration'}
|
||||
subtitle={''}
|
||||
on:click={runTemplateMigration}
|
||||
jobStatus={allJobsStatus?.isStorageMigrationActive}
|
||||
waitingJobCount={allJobsStatus?.storageMigrationQueueCount.waiting}
|
||||
activeJobCount={allJobsStatus?.storageMigrationQueueCount.active}
|
||||
>
|
||||
Apply the current
|
||||
<a
|
||||
href="/admin/system-settings?open=storage-template"
|
||||
class="text-immich-primary dark:text-immich-dark-primary">Storage template</a
|
||||
<JobTile
|
||||
title={'Detect objects'}
|
||||
subtitle={'Run machine learning process to detect and classify objects'}
|
||||
on:click={() =>
|
||||
run(JobId.MachineLearning, 'object detection', 'No missing object detection found')}
|
||||
jobCounts={jobs[JobId.MachineLearning]}
|
||||
>
|
||||
to previously uploaded assets
|
||||
</JobTile>
|
||||
Note that some assets may not have any objects detected, this is normal.
|
||||
</JobTile>
|
||||
|
||||
<JobTile
|
||||
title={'Video transcoding'}
|
||||
subtitle={'Run video transcoding process to transcode videos not in the desired format'}
|
||||
on:click={() =>
|
||||
run(
|
||||
JobId.VideoConversion,
|
||||
'video conversion',
|
||||
'No videos without an encoded version found'
|
||||
)}
|
||||
jobCounts={jobs[JobId.MachineLearning]}
|
||||
/>
|
||||
|
||||
<JobTile
|
||||
title={'Storage migration'}
|
||||
subtitle={''}
|
||||
on:click={() =>
|
||||
run(
|
||||
JobId.StorageTemplateMigration,
|
||||
'storage template migration',
|
||||
'All files have been migrated to the new storage template'
|
||||
)}
|
||||
jobCounts={jobs[JobId.StorageTemplateMigration]}
|
||||
>
|
||||
Apply the current
|
||||
<a
|
||||
href="/admin/system-settings?open=storage-template"
|
||||
class="text-immich-primary dark:text-immich-dark-primary">Storage template</a
|
||||
>
|
||||
to previously uploaded assets
|
||||
</JobTile>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user