0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-03-04 02:11:44 -05:00

refactor(server): immich worker (#13871)

refactor(server): immich work
This commit is contained in:
Jason Rasmussen 2024-11-01 17:19:36 -04:00 committed by GitHub
parent cdabd08139
commit fed882a28a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 26 additions and 35 deletions

View file

@ -6,6 +6,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { ClsModule } from 'nestjs-cls'; import { ClsModule } from 'nestjs-cls';
import { OpenTelemetryModule } from 'nestjs-otel'; import { OpenTelemetryModule } from 'nestjs-otel';
import { commands } from 'src/commands'; import { commands } from 'src/commands';
import { IWorker } from 'src/constants';
import { controllers } from 'src/controllers'; import { controllers } from 'src/controllers';
import { entities } from 'src/entities'; import { entities } from 'src/entities';
import { ImmichWorker } from 'src/enum'; import { ImmichWorker } from 'src/enum';
@ -57,12 +58,9 @@ const imports = [
TypeOrmModule.forFeature(entities), TypeOrmModule.forFeature(entities),
]; ];
abstract class BaseModule implements OnModuleInit, OnModuleDestroy { class BaseModule implements OnModuleInit, OnModuleDestroy {
private get worker() {
return this.getWorker();
}
constructor( constructor(
@Inject(IWorker) private worker: ImmichWorker,
@Inject(ILoggerRepository) logger: ILoggerRepository, @Inject(ILoggerRepository) logger: ILoggerRepository,
@Inject(IEventRepository) private eventRepository: IEventRepository, @Inject(IEventRepository) private eventRepository: IEventRepository,
@Inject(IJobRepository) private jobRepository: IJobRepository, @Inject(IJobRepository) private jobRepository: IJobRepository,
@ -71,8 +69,6 @@ abstract class BaseModule implements OnModuleInit, OnModuleDestroy {
logger.setAppName(this.worker); logger.setAppName(this.worker);
} }
abstract getWorker(): ImmichWorker;
async onModuleInit() { async onModuleInit() {
this.telemetryRepository.setup({ repositories: repositories.map(({ useClass }) => useClass) }); this.telemetryRepository.setup({ repositories: repositories.map(({ useClass }) => useClass) });
@ -94,23 +90,15 @@ abstract class BaseModule implements OnModuleInit, OnModuleDestroy {
@Module({ @Module({
imports: [...imports, ScheduleModule.forRoot()], imports: [...imports, ScheduleModule.forRoot()],
controllers: [...controllers], controllers: [...controllers],
providers: [...common, ...middleware], providers: [...common, ...middleware, { provide: IWorker, useValue: ImmichWorker.API }],
}) })
export class ApiModule extends BaseModule { export class ApiModule extends BaseModule {}
getWorker() {
return ImmichWorker.API;
}
}
@Module({ @Module({
imports: [...imports], imports: [...imports],
providers: [...common, SchedulerRegistry], providers: [...common, { provide: IWorker, useValue: ImmichWorker.MICROSERVICES }, SchedulerRegistry],
}) })
export class MicroservicesModule extends BaseModule { export class MicroservicesModule extends BaseModule {}
getWorker() {
return ImmichWorker.MICROSERVICES;
}
}
@Module({ @Module({
imports: [...imports], imports: [...imports],

View file

@ -13,6 +13,8 @@ export const ADDED_IN_PREFIX = 'This property was added in ';
export const SALT_ROUNDS = 10; export const SALT_ROUNDS = 10;
export const IWorker = 'IWorker';
const { version } = JSON.parse(readFileSync('./package.json', 'utf8')); const { version } = JSON.parse(readFileSync('./package.json', 'utf8'));
export const serverVersion = new SemVer(version); export const serverVersion = new SemVer(version);

View file

@ -1,9 +1,10 @@
import { BadRequestException, Inject } from '@nestjs/common'; import { BadRequestException, Inject, Optional } from '@nestjs/common';
import sanitize from 'sanitize-filename'; import sanitize from 'sanitize-filename';
import { SystemConfig } from 'src/config'; import { SystemConfig } from 'src/config';
import { SALT_ROUNDS } from 'src/constants'; import { IWorker, SALT_ROUNDS } from 'src/constants';
import { StorageCore } from 'src/cores/storage.core'; import { StorageCore } from 'src/cores/storage.core';
import { UserEntity } from 'src/entities/user.entity'; import { UserEntity } from 'src/entities/user.entity';
import { ImmichWorker } from 'src/enum';
import { IAccessRepository } from 'src/interfaces/access.interface'; import { IAccessRepository } from 'src/interfaces/access.interface';
import { IActivityRepository } from 'src/interfaces/activity.interface'; import { IActivityRepository } from 'src/interfaces/activity.interface';
import { IAlbumUserRepository } from 'src/interfaces/album-user.interface'; import { IAlbumUserRepository } from 'src/interfaces/album-user.interface';
@ -49,6 +50,7 @@ export class BaseService {
protected storageCore: StorageCore; protected storageCore: StorageCore;
constructor( constructor(
@Inject(IWorker) @Optional() protected worker: ImmichWorker | undefined,
@Inject(ILoggerRepository) protected logger: ILoggerRepository, @Inject(ILoggerRepository) protected logger: ILoggerRepository,
@Inject(IAccessRepository) protected accessRepository: IAccessRepository, @Inject(IAccessRepository) protected accessRepository: IAccessRepository,
@Inject(IActivityRepository) protected activityRepository: IActivityRepository, @Inject(IActivityRepository) protected activityRepository: IActivityRepository,

View file

@ -18,7 +18,9 @@ describe(JobService.name, () => {
let telemetryMock: Mocked<ITelemetryRepository>; let telemetryMock: Mocked<ITelemetryRepository>;
beforeEach(() => { beforeEach(() => {
({ sut, assetMock, jobMock, loggerMock, telemetryMock } = newTestService(JobService)); ({ sut, assetMock, jobMock, loggerMock, telemetryMock } = newTestService(JobService, {
worker: ImmichWorker.MICROSERVICES,
}));
}); });
it('should work', () => { it('should work', () => {
@ -27,7 +29,6 @@ describe(JobService.name, () => {
describe('onConfigUpdate', () => { describe('onConfigUpdate', () => {
it('should update concurrency', () => { it('should update concurrency', () => {
sut.onBootstrap(ImmichWorker.MICROSERVICES);
sut.onConfigUpdate({ oldConfig: defaults, newConfig: defaults }); sut.onConfigUpdate({ oldConfig: defaults, newConfig: defaults });
expect(jobMock.setConcurrency).toHaveBeenCalledTimes(15); expect(jobMock.setConcurrency).toHaveBeenCalledTimes(15);

View file

@ -38,16 +38,9 @@ const asJobItem = (dto: JobCreateDto): JobItem => {
@Injectable() @Injectable()
export class JobService extends BaseService { export class JobService extends BaseService {
private isMicroservices = false;
@OnEvent({ name: 'app.bootstrap' })
onBootstrap(app: ArgOf<'app.bootstrap'>) {
this.isMicroservices = app === ImmichWorker.MICROSERVICES;
}
@OnEvent({ name: 'config.update', server: true }) @OnEvent({ name: 'config.update', server: true })
onConfigUpdate({ newConfig: config }: ArgOf<'config.update'>) { onConfigUpdate({ newConfig: config }: ArgOf<'config.update'>) {
if (!this.isMicroservices) { if (this.worker !== ImmichWorker.MICROSERVICES) {
return; return;
} }

View file

@ -1,6 +1,7 @@
import { ChildProcessWithoutNullStreams } from 'node:child_process'; import { ChildProcessWithoutNullStreams } from 'node:child_process';
import { Writable } from 'node:stream'; import { Writable } from 'node:stream';
import { PNG } from 'pngjs'; import { PNG } from 'pngjs';
import { ImmichWorker } from 'src/enum';
import { IMetadataRepository } from 'src/interfaces/metadata.interface'; import { IMetadataRepository } from 'src/interfaces/metadata.interface';
import { BaseService } from 'src/services/base.service'; import { BaseService } from 'src/services/base.service';
import { newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; import { newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
@ -44,8 +45,9 @@ import { newViewRepositoryMock } from 'test/repositories/view.repository.mock';
import { Readable } from 'typeorm/platform/PlatformTools'; import { Readable } from 'typeorm/platform/PlatformTools';
import { Mocked, vitest } from 'vitest'; import { Mocked, vitest } from 'vitest';
type RepositoryOverrides = { type Overrides = {
metadataRepository: IMetadataRepository; worker?: ImmichWorker;
metadataRepository?: IMetadataRepository;
}; };
type BaseServiceArgs = ConstructorParameters<typeof BaseService>; type BaseServiceArgs = ConstructorParameters<typeof BaseService>;
type Constructor<Type, Args extends Array<any>> = { type Constructor<Type, Args extends Array<any>> = {
@ -54,9 +56,11 @@ type Constructor<Type, Args extends Array<any>> = {
export const newTestService = <T extends BaseService>( export const newTestService = <T extends BaseService>(
Service: Constructor<T, BaseServiceArgs>, Service: Constructor<T, BaseServiceArgs>,
overrides?: RepositoryOverrides, overrides?: Overrides,
) => { ) => {
const { metadataRepository } = overrides || {}; const { metadataRepository, worker: workerOverride } = overrides || {};
const worker = workerOverride || ImmichWorker.API;
const accessMock = newAccessRepositoryMock(); const accessMock = newAccessRepositoryMock();
const loggerMock = newLoggerRepositoryMock(); const loggerMock = newLoggerRepositoryMock();
@ -98,6 +102,7 @@ export const newTestService = <T extends BaseService>(
const viewMock = newViewRepositoryMock(); const viewMock = newViewRepositoryMock();
const sut = new Service( const sut = new Service(
worker,
loggerMock, loggerMock,
accessMock, accessMock,
activityMock, activityMock,