forked from Cutlery/immich
check import paths when testing offline
This commit is contained in:
parent
9a707874e4
commit
f5073a1a7a
@ -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[];
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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 },
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user