1
0
forked from Cutlery/immich

check import paths when testing offline

This commit is contained in:
Jonathan Jogenfors 2024-03-20 08:17:22 +01:00
parent 9a707874e4
commit f5073a1a7a
3 changed files with 50 additions and 11 deletions

View File

@ -21,6 +21,10 @@ export interface ILibraryRefreshJob extends IEntityJob {
refreshAllFiles: boolean;
}
export interface ILibraryOfflineJob extends IEntityJob {
importPaths: string[];
}
export interface IBulkEntityJob extends IBaseJob {
ids: string[];
}

View File

@ -20,7 +20,7 @@ import {
import { when } from 'jest-when';
import { R_OK } from 'node:constants';
import { Stats } from 'node:fs';
import { IEntityJob, ILibraryFileJob, ILibraryRefreshJob, JobName } from '../job';
import { IEntityJob, ILibraryFileJob, ILibraryOfflineJob, ILibraryRefreshJob, JobName } from '../job';
import {
IAssetRepository,
ICryptoRepository,
@ -277,8 +277,9 @@ describe(LibraryService.name, () => {
describe('handleOfflineCheck', () => {
it('should set missing assets offline', async () => {
const mockAssetJob: IEntityJob = {
const mockAssetJob: ILibraryOfflineJob = {
id: assetStub.external.id,
importPaths: ['/'],
};
assetMock.getById.mockResolvedValue(assetStub.external);
@ -290,9 +291,25 @@ describe(LibraryService.name, () => {
expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.external.id, isOffline: true });
});
it('should skip an offline asset', async () => {
const mockAssetJob: IEntityJob = {
it('should set an asset outside of import paths as offline', async () => {
const mockAssetJob: ILibraryOfflineJob = {
id: assetStub.external.id,
importPaths: ['/data/user2'],
};
assetMock.getById.mockResolvedValue(assetStub.external);
storageMock.checkFileExists.mockResolvedValue(true);
await sut.handleOfflineCheck(mockAssetJob);
expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.external.id, isOffline: true });
});
it('should skip an offline asset', async () => {
const mockAssetJob: ILibraryOfflineJob = {
id: assetStub.external.id,
importPaths: ['/'],
};
assetMock.getById.mockResolvedValue(assetStub.offline);
@ -306,8 +323,9 @@ describe(LibraryService.name, () => {
});
it('should skip a nonexistent asset id', async () => {
const mockAssetJob: IEntityJob = {
const mockAssetJob: ILibraryOfflineJob = {
id: assetStub.external.id,
importPaths: ['/'],
};
assetMock.getById.mockImplementation(() => Promise.resolve(null));

View File

@ -1,4 +1,4 @@
import { AssetType, LibraryType } from '@app/infra/entities';
import { AssetEntity, AssetType, LibraryType } from '@app/infra/entities';
import { ImmichLogger } from '@app/infra/logger';
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
@ -10,7 +10,15 @@ import picomatch from 'picomatch';
import { AccessCore } from '../access';
import { mimeTypes } from '../domain.constant';
import { handlePromiseError, usePagination, validateCronExpression } from '../domain.util';
import { IBaseJob, IEntityJob, ILibraryFileJob, ILibraryRefreshJob, JOBS_ASSET_PAGINATION_SIZE, JobName } from '../job';
import {
IBaseJob,
IEntityJob,
ILibraryFileJob,
ILibraryOfflineJob,
ILibraryRefreshJob,
JOBS_ASSET_PAGINATION_SIZE,
JobName,
} from '../job';
import {
DatabaseLock,
IAccessRepository,
@ -575,7 +583,7 @@ export class LibraryService extends EventEmitter {
}
// Check if an asset is has no file or is outside of import paths, marking it as offline
async handleOfflineCheck(job: IEntityJob): Promise<JobStatus> {
async handleOfflineCheck(job: ILibraryOfflineJob): Promise<JobStatus> {
const asset = await this.assetRepository.getById(job.id);
if (!asset || asset.isOffline) {
@ -585,7 +593,16 @@ export class LibraryService extends EventEmitter {
const exists = await this.storageRepository.checkFileExists(asset.originalPath, R_OK);
if (exists) {
let existsInImportPath = false;
for (const importPath of job.importPaths) {
if (asset.originalPath.startsWith(importPath)) {
existsInImportPath = true;
break;
}
}
if (exists && existsInImportPath) {
this.logger.verbose(`Asset is still online: ${asset.originalPath}`);
} else {
this.logger.debug(`Marking asset as offline: ${asset.originalPath}`);
@ -657,9 +674,9 @@ export class LibraryService extends EventEmitter {
`Queuing online check of ${existingAssetPage.value.length} asset(s) in library ${library.id}...`,
);
await this.jobRepository.queueAll(
existingAssetPage.value.map((asset) => ({
existingAssetPage.value.map((asset: AssetEntity) => ({
name: JobName.LIBRARY_CHECK_OFFLINE,
data: { id: asset.id },
data: { id: asset.id, importPaths: validImportPaths },
})),
);
}