mirror of
https://github.com/immich-app/immich.git
synced 2025-12-27 09:14:55 +03:00
feat: manually trigger integrity jobs
feat: update summary after job runs
This commit is contained in:
@@ -16,6 +16,30 @@
|
||||
{ title: $t('admin.memory_cleanup_job'), value: ManualJobName.MemoryCleanup },
|
||||
{ title: $t('admin.memory_generate_job'), value: ManualJobName.MemoryCreate },
|
||||
{ title: $t('admin.backup_database'), value: ManualJobName.BackupDatabase },
|
||||
{
|
||||
title: $t('admin.maintenance_integrity_missing_file_job'),
|
||||
value: ManualJobName.IntegrityMissingFiles,
|
||||
},
|
||||
{
|
||||
title: $t('admin.maintenance_integrity_orphan_file_job'),
|
||||
value: ManualJobName.IntegrityOrphanFiles,
|
||||
},
|
||||
{
|
||||
title: $t('admin.maintenance_integrity_checksum_mismatch_job'),
|
||||
value: ManualJobName.IntegrityChecksumMismatch,
|
||||
},
|
||||
{
|
||||
title: $t('admin.maintenance_integrity_missing_file_refresh_job'),
|
||||
value: ManualJobName.IntegrityMissingFilesRefresh,
|
||||
},
|
||||
{
|
||||
title: $t('admin.maintenance_integrity_orphan_file_refresh_job'),
|
||||
value: ManualJobName.IntegrityOrphanFilesRefresh,
|
||||
},
|
||||
{
|
||||
title: $t('admin.maintenance_integrity_checksum_mismatch_refresh_job'),
|
||||
value: ManualJobName.IntegrityChecksumMismatchRefresh,
|
||||
},
|
||||
].map(({ value, title }) => ({ id: value, label: title, value }));
|
||||
|
||||
let selectedJob: ComboBoxOption | undefined = $state(undefined);
|
||||
|
||||
@@ -2,10 +2,22 @@
|
||||
import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte';
|
||||
import ServerStatisticsCard from '$lib/components/server-statistics/ServerStatisticsCard.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { asyncTimeout } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { MaintenanceAction, setMaintenanceMode } from '@immich/sdk';
|
||||
import { Button, HStack, Text } from '@immich/ui';
|
||||
import {
|
||||
createJob,
|
||||
getIntegrityReportSummary,
|
||||
getQueuesLegacy,
|
||||
IntegrityReportType,
|
||||
MaintenanceAction,
|
||||
ManualJobName,
|
||||
setMaintenanceMode,
|
||||
type MaintenanceIntegrityReportSummaryResponseDto,
|
||||
type QueuesResponseLegacyDto,
|
||||
} from '@immich/sdk';
|
||||
import { Button, HStack, Text, toastManager } from '@immich/ui';
|
||||
import { mdiProgressWrench } from '@mdi/js';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
@@ -15,6 +27,14 @@
|
||||
|
||||
let { data }: Props = $props();
|
||||
|
||||
let integrityReport: MaintenanceIntegrityReportSummaryResponseDto | undefined = $state(data.integrityReport);
|
||||
|
||||
const TYPES: IntegrityReportType[] = [
|
||||
IntegrityReportType.OrphanFile,
|
||||
IntegrityReportType.MissingFile,
|
||||
IntegrityReportType.ChecksumMismatch,
|
||||
];
|
||||
|
||||
async function switchToMaintenance() {
|
||||
try {
|
||||
await setMaintenanceMode({
|
||||
@@ -26,6 +46,56 @@
|
||||
handleError(error, $t('admin.maintenance_start_error'));
|
||||
}
|
||||
}
|
||||
|
||||
let jobs: QueuesResponseLegacyDto | undefined = $state();
|
||||
let expectingUpdate: boolean = $state(false);
|
||||
|
||||
async function runJob(reportType: IntegrityReportType, refreshOnly?: boolean) {
|
||||
let name: ManualJobName;
|
||||
switch (reportType) {
|
||||
case IntegrityReportType.OrphanFile: {
|
||||
name = refreshOnly ? ManualJobName.IntegrityOrphanFilesRefresh : ManualJobName.IntegrityOrphanFiles;
|
||||
break;
|
||||
}
|
||||
case IntegrityReportType.MissingFile: {
|
||||
name = refreshOnly ? ManualJobName.IntegrityMissingFilesRefresh : ManualJobName.IntegrityMissingFiles;
|
||||
break;
|
||||
}
|
||||
case IntegrityReportType.ChecksumMismatch: {
|
||||
name = refreshOnly ? ManualJobName.IntegrityChecksumMismatchRefresh : ManualJobName.IntegrityChecksumMismatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await createJob({ jobCreateDto: { name } });
|
||||
if (jobs) {
|
||||
expectingUpdate = true;
|
||||
jobs.backgroundTask.queueStatus.isActive = true;
|
||||
}
|
||||
toastManager.success($t('admin.job_created'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_submit_job'));
|
||||
}
|
||||
}
|
||||
|
||||
let running = true;
|
||||
|
||||
onMount(async () => {
|
||||
while (running) {
|
||||
jobs = await getQueuesLegacy();
|
||||
if (jobs.backgroundTask.queueStatus.isActive) {
|
||||
expectingUpdate = true;
|
||||
} else if (expectingUpdate) {
|
||||
integrityReport = await getIntegrityReportSummary();
|
||||
}
|
||||
await asyncTimeout(5000);
|
||||
}
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
running = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<AdminPageLayout breadcrumbs={[{ title: data.meta.title }]}>
|
||||
@@ -48,17 +118,33 @@
|
||||
<p class="text-sm dark:text-immich-dark-fg uppercase">{$t('admin.maintenance_integrity_report')}</p>
|
||||
|
||||
<div class="mt-5 hidden justify-between lg:flex gap-4">
|
||||
{#each ['orphan_file', 'missing_file', 'checksum_mismatch'] as const as reportType (reportType)}
|
||||
{#each TYPES as reportType (reportType)}
|
||||
<ServerStatisticsCard
|
||||
title={$t(`admin.maintenance_integrity_${reportType}`)}
|
||||
value={data.integrityReport[reportType]}
|
||||
value={integrityReport[reportType]}
|
||||
>
|
||||
{#snippet footer()}
|
||||
<Button
|
||||
href={`${AppRoute.ADMIN_MAINTENANCE_INTEGRITY_REPORT + reportType}`}
|
||||
size="tiny"
|
||||
class="self-end mt-1">View Report</Button
|
||||
>
|
||||
<HStack gap={1} class="justify-end">
|
||||
<Button
|
||||
onclick={() => runJob(reportType)}
|
||||
size="tiny"
|
||||
variant="ghost"
|
||||
class="self-end mt-1"
|
||||
disabled={jobs?.backgroundTask.queueStatus.isActive}>Check All</Button
|
||||
>
|
||||
<Button
|
||||
onclick={() => runJob(reportType, true)}
|
||||
size="tiny"
|
||||
variant="ghost"
|
||||
class="self-end mt-1"
|
||||
disabled={jobs?.backgroundTask.queueStatus.isActive}>Refresh</Button
|
||||
>
|
||||
<Button
|
||||
href={`${AppRoute.ADMIN_MAINTENANCE_INTEGRITY_REPORT + reportType}`}
|
||||
size="tiny"
|
||||
class="self-end mt-1">View</Button
|
||||
>
|
||||
</HStack>
|
||||
{/snippet}
|
||||
</ServerStatisticsCard>
|
||||
{/each}
|
||||
|
||||
Reference in New Issue
Block a user