make event strings an enum

This commit is contained in:
Jonathan Jogenfors
2024-02-29 22:58:49 +01:00
parent a2ab2fd6f6
commit 967b30cfa5
6 changed files with 38 additions and 27 deletions

View File

@@ -1,4 +1,4 @@
import { LibraryResponseDto, LibraryService, LoginResponseDto } from '@app/domain';
import { LibraryResponseDto, LibraryService, LoginResponseDto, StorageEvent } from '@app/domain';
import { AssetType, LibraryType } from '@app/infra/entities';
import fs from 'node:fs/promises';
import path from 'node:path';
@@ -57,7 +57,7 @@ describe(`Library watcher (e2e)`, () => {
`${IMMICH_TEST_ASSET_TEMP_PATH}/file.jpg`,
);
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, StorageEvent.ADD);
const afterAssets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(afterAssets.length).toEqual(1);
@@ -84,10 +84,10 @@ describe(`Library watcher (e2e)`, () => {
`${IMMICH_TEST_ASSET_TEMP_PATH}/file5.jPg`,
);
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, StorageEvent.ADD);
await waitForEvent(libraryService, StorageEvent.ADD);
await waitForEvent(libraryService, StorageEvent.ADD);
await waitForEvent(libraryService, StorageEvent.ADD);
const afterAssets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(afterAssets.length).toEqual(4);
@@ -99,7 +99,7 @@ describe(`Library watcher (e2e)`, () => {
`${IMMICH_TEST_ASSET_TEMP_PATH}/file.jpg`,
);
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, StorageEvent.ADD);
const originalAssets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(originalAssets.length).toEqual(1);
@@ -109,7 +109,7 @@ describe(`Library watcher (e2e)`, () => {
`${IMMICH_TEST_ASSET_TEMP_PATH}/file.jpg`,
);
await waitForEvent(libraryService, 'change');
await waitForEvent(libraryService, StorageEvent.CHANGE);
const afterAssets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(afterAssets).toEqual([
@@ -161,9 +161,9 @@ describe(`Library watcher (e2e)`, () => {
`${IMMICH_TEST_ASSET_TEMP_PATH}/dir3/file4.jpg`,
);
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, StorageEvent.ADD);
await waitForEvent(libraryService, StorageEvent.ADD);
await waitForEvent(libraryService, StorageEvent.ADD);
const assets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(assets.length).toEqual(3);
@@ -175,14 +175,14 @@ describe(`Library watcher (e2e)`, () => {
`${IMMICH_TEST_ASSET_TEMP_PATH}/dir1/file.jpg`,
);
await waitForEvent(libraryService, 'add');
await waitForEvent(libraryService, StorageEvent.ADD);
const addedAssets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(addedAssets.length).toEqual(1);
await fs.unlink(`${IMMICH_TEST_ASSET_TEMP_PATH}/dir1/file.jpg`);
await waitForEvent(libraryService, 'unlink');
await waitForEvent(libraryService, StorageEvent.UNLINK);
const afterAssets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(afterAssets[0].isOffline).toEqual(true);

View File

@@ -1312,7 +1312,7 @@ describe(LibraryService.name, () => {
storageMock.watch.mockImplementation(makeMockWatcher({ close: mockClose }));
await sut.init();
await sut.tearDown();
await sut.teardown();
expect(mockClose).toHaveBeenCalledTimes(2);
});

View File

@@ -23,6 +23,7 @@ import {
IStorageRepository,
ISystemConfigRepository,
IUserRepository,
StorageEvent,
WithProperty,
} from '../repositories';
import { SystemConfigCore } from '../system-config';
@@ -141,7 +142,7 @@ export class LibraryService extends EventEmitter {
if (matcher(path)) {
await this.scanAssets(library.id, [path], library.ownerId, false);
}
this.emit('add', path);
this.emit(StorageEvent.ADD, path);
},
onChange: async (path) => {
this.logger.debug(`Detected file change for ${path} in library ${library.id}`);
@@ -149,7 +150,7 @@ export class LibraryService extends EventEmitter {
// Note: if the changed file was not previously imported, it will be imported now.
await this.scanAssets(library.id, [path], library.ownerId, false);
}
this.emit('change', path);
this.emit(StorageEvent.CHANGE, path);
},
onUnlink: async (path) => {
this.logger.debug(`Detected deleted file at ${path} in library ${library.id}`);
@@ -157,11 +158,12 @@ export class LibraryService extends EventEmitter {
if (asset && matcher(path)) {
await this.assetRepository.save({ id: asset.id, isOffline: true });
}
this.emit('unlink', path);
this.emit(StorageEvent.UNLINK, path);
},
onError: (error) => {
// TODO: should we log, or throw an exception?
this.logger.error(`Library watcher for library ${library.id} encountered error: ${error}`);
this.emit(StorageEvent.ERROR, error);
},
},
);

View File

@@ -31,6 +31,14 @@ export interface WatchEvents {
onError(error: Error): void;
}
export enum StorageEvent {
READY = 'ready',
ADD = 'add',
CHANGE = 'change',
UNLINK = 'unlink',
ERROR = 'error',
}
export interface IStorageRepository {
createZipStream(): ImmichZipStream;
createReadStream(filepath: string, mimeType?: string | null): Promise<ImmichReadStream>;

View File

@@ -1,11 +1,12 @@
import {
CrawlOptionsDto,
DiskUsage,
IStorageRepository,
ImmichReadStream,
ImmichZipStream,
IStorageRepository,
mimeTypes,
StorageEvent,
WatchEvents,
mimeTypes,
} from '@app/domain';
import { ImmichLogger } from '@app/infra/logger';
import archiver from 'archiver';
@@ -141,11 +142,11 @@ export class FilesystemProvider implements IStorageRepository {
watch(paths: string[], options: WatchOptions, events: Partial<WatchEvents>) {
const watcher = chokidar.watch(paths, options);
watcher.on('ready', () => events.onReady?.());
watcher.on('add', (path) => events.onAdd?.(path));
watcher.on('change', (path) => events.onChange?.(path));
watcher.on('unlink', (path) => events.onUnlink?.(path));
watcher.on('error', (error) => events.onError?.(error));
watcher.on(StorageEvent.READY, () => events.onReady?.());
watcher.on(StorageEvent.ADD, (path) => events.onAdd?.(path));
watcher.on(StorageEvent.CHANGE, (path) => events.onChange?.(path));
watcher.on(StorageEvent.UNLINK, (path) => events.onUnlink?.(path));
watcher.on(StorageEvent.ERROR, (error) => events.onError?.(error));
return () => watcher.close();
}

View File

@@ -1,4 +1,4 @@
import { IJobRepository, IMediaRepository, JobItem, JobItemHandler, QueueName } from '@app/domain';
import { IJobRepository, IMediaRepository, JobItem, JobItemHandler, QueueName, StorageEvent } from '@app/domain';
import { AppModule } from '@app/immich';
import { InfraModule, InfraTestModule, dataSource } from '@app/infra';
import { MediaRepository } from '@app/infra/repositories';
@@ -141,7 +141,7 @@ export const testApp = {
export function waitForEvent<T>(emitter: EventEmitter, event: string): Promise<T> {
return new Promise((resolve, reject) => {
const success = (value: T) => {
emitter.off('error', fail);
emitter.off(StorageEvent.ERROR, fail);
resolve(value);
};
const fail = (error: Error) => {
@@ -149,7 +149,7 @@ export function waitForEvent<T>(emitter: EventEmitter, event: string): Promise<T
reject(error);
};
emitter.once(event, success);
emitter.once('error', fail);
emitter.once(StorageEvent.ERROR, fail);
});
}