From 0243570c0ba870b9740b6dec8c2e170209e7b1aa Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Mon, 9 Oct 2023 02:51:03 +0200 Subject: [PATCH] fix(server): make system config core singleton (#4392) * make system config core singleton * refactor * fix tests * chore: fix tests --------- Co-authored-by: Jason Rasmussen --- server/src/domain/asset/asset.service.ts | 2 +- server/src/domain/auth/auth.service.ts | 2 +- server/src/domain/job/job.service.spec.ts | 3 +-- server/src/domain/job/job.service.ts | 2 +- server/src/domain/media/media.service.ts | 2 +- server/src/domain/metadata/metadata.service.ts | 2 +- server/src/domain/person/person.service.ts | 2 +- server/src/domain/search/search.service.ts | 2 +- .../domain/server-info/server-info.service.ts | 2 +- .../src/domain/smart-info/smart-info.service.ts | 2 +- .../storage-template.service.ts | 2 +- .../domain/system-config/system-config.core.ts | 17 ++++++++++++++--- .../system-config/system-config.service.spec.ts | 2 +- .../system-config/system-config.service.ts | 2 +- .../system-config.repository.mock.ts | 8 ++++++-- 15 files changed, 33 insertions(+), 19 deletions(-) diff --git a/server/src/domain/asset/asset.service.ts b/server/src/domain/asset/asset.service.ts index b04ae646bb..f6f7aeec07 100644 --- a/server/src/domain/asset/asset.service.ts +++ b/server/src/domain/asset/asset.service.ts @@ -77,7 +77,7 @@ export class AssetService { ) { this.access = new AccessCore(accessRepository); this.storageCore = new StorageCore(storageRepository); - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); } canUploadFile({ authUser, fieldName, file }: UploadRequest): true { diff --git a/server/src/domain/auth/auth.service.ts b/server/src/domain/auth/auth.service.ts index 7e0a4d39da..de18bc07c9 100644 --- a/server/src/domain/auth/auth.service.ts +++ b/server/src/domain/auth/auth.service.ts @@ -71,7 +71,7 @@ export class AuthService { @Inject(ISharedLinkRepository) private sharedLinkRepository: ISharedLinkRepository, @Inject(IKeyRepository) private keyRepository: IKeyRepository, ) { - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); this.userCore = new UserCore(userRepository, libraryRepository, cryptoRepository); custom.setHttpOptionsDefaults({ timeout: 30000 }); diff --git a/server/src/domain/job/job.service.spec.ts b/server/src/domain/job/job.service.spec.ts index 3a44b71d80..505bca7f79 100644 --- a/server/src/domain/job/job.service.spec.ts +++ b/server/src/domain/job/job.service.spec.ts @@ -223,8 +223,7 @@ describe(JobService.name, () => { it('should subscribe to config changes', async () => { await sut.registerHandlers(makeMockHandlers(false)); - const configCore = new SystemConfigCore(newSystemConfigRepositoryMock()); - configCore.config$.next({ + SystemConfigCore.create(newSystemConfigRepositoryMock(false)).config$.next({ job: { [QueueName.BACKGROUND_TASK]: { concurrency: 10 }, [QueueName.CLIP_ENCODING]: { concurrency: 10 }, diff --git a/server/src/domain/job/job.service.ts b/server/src/domain/job/job.service.ts index 9eb2e10cd8..8c90de9726 100644 --- a/server/src/domain/job/job.service.ts +++ b/server/src/domain/job/job.service.ts @@ -21,7 +21,7 @@ export class JobService { @Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository, @Inject(IPersonRepository) private personRepository: IPersonRepository, ) { - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); } async handleCommand(queueName: QueueName, dto: JobCommandDto): Promise { diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index f836026de5..ebf57de94c 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -24,7 +24,7 @@ export class MediaService { @Inject(IStorageRepository) private storageRepository: IStorageRepository, @Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository, ) { - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); this.storageCore = new StorageCore(this.storageRepository); } diff --git a/server/src/domain/metadata/metadata.service.ts b/server/src/domain/metadata/metadata.service.ts index 7b1508bcef..b00e9eedd2 100644 --- a/server/src/domain/metadata/metadata.service.ts +++ b/server/src/domain/metadata/metadata.service.ts @@ -67,7 +67,7 @@ export class MetadataService { @Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository, ) { this.storageCore = new StorageCore(storageRepository); - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); this.configCore.config$.subscribe(() => this.init()); } diff --git a/server/src/domain/person/person.service.ts b/server/src/domain/person/person.service.ts index 11177fce7e..c21e654b2a 100644 --- a/server/src/domain/person/person.service.ts +++ b/server/src/domain/person/person.service.ts @@ -49,7 +49,7 @@ export class PersonService { ) { this.access = new AccessCore(accessRepository); this.storageCore = new StorageCore(storageRepository); - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); } async getAll(authUser: AuthUserDto, dto: PersonSearchDto): Promise { diff --git a/server/src/domain/search/search.service.ts b/server/src/domain/search/search.service.ts index a8f6250204..1108977bad 100644 --- a/server/src/domain/search/search.service.ts +++ b/server/src/domain/search/search.service.ts @@ -57,7 +57,7 @@ export class SearchService { @Inject(ISearchRepository) private searchRepository: ISearchRepository, @Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository, ) { - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); } teardown() { diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index d54aab682f..d480def076 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -24,7 +24,7 @@ export class ServerInfoService { @Inject(IUserRepository) private userRepository: IUserRepository, @Inject(IStorageRepository) private storageRepository: IStorageRepository, ) { - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); this.storageCore = new StorageCore(storageRepository); } diff --git a/server/src/domain/smart-info/smart-info.service.ts b/server/src/domain/smart-info/smart-info.service.ts index d057d20154..a490e19f3a 100644 --- a/server/src/domain/smart-info/smart-info.service.ts +++ b/server/src/domain/smart-info/smart-info.service.ts @@ -17,7 +17,7 @@ export class SmartInfoService { @Inject(ISmartInfoRepository) private repository: ISmartInfoRepository, @Inject(IMachineLearningRepository) private machineLearning: IMachineLearningRepository, ) { - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); } async handleQueueObjectTagging({ force }: IBaseJob) { diff --git a/server/src/domain/storage-template/storage-template.service.ts b/server/src/domain/storage-template/storage-template.service.ts index 3ab9694c37..789c91d4d8 100644 --- a/server/src/domain/storage-template/storage-template.service.ts +++ b/server/src/domain/storage-template/storage-template.service.ts @@ -42,7 +42,7 @@ export class StorageTemplateService { @Inject(IUserRepository) private userRepository: IUserRepository, ) { this.storageTemplate = this.compile(config.storageTemplate.template); - this.configCore = new SystemConfigCore(configRepository); + this.configCore = SystemConfigCore.create(configRepository); this.configCore.addValidator((config) => this.validate(config)); this.configCore.config$.subscribe((config) => this.onConfig(config)); this.storageCore = new StorageCore(storageRepository); diff --git a/server/src/domain/system-config/system-config.core.ts b/server/src/domain/system-config/system-config.core.ts index 07e31aa5b4..a97636e01c 100644 --- a/server/src/domain/system-config/system-config.core.ts +++ b/server/src/domain/system-config/system-config.core.ts @@ -134,7 +134,7 @@ export enum FeatureFlag { export type FeatureFlags = Record; -const singleton = new Subject(); +let instance: SystemConfigCore | null; @Injectable() export class SystemConfigCore { @@ -142,9 +142,20 @@ export class SystemConfigCore { private validators: SystemConfigValidator[] = []; private configCache: SystemConfig | null = null; - public config$ = singleton; + public config$ = new Subject(); - constructor(private repository: ISystemConfigRepository) {} + private constructor(private repository: ISystemConfigRepository) {} + + static create(repository: ISystemConfigRepository) { + if (!instance) { + instance = new SystemConfigCore(repository); + } + return instance; + } + + static reset() { + instance = null; + } async requireFeature(feature: FeatureFlag) { const hasFeature = await this.hasFeature(feature); diff --git a/server/src/domain/system-config/system-config.service.spec.ts b/server/src/domain/system-config/system-config.service.spec.ts index 8da7ae4aef..6f97c02f39 100644 --- a/server/src/domain/system-config/system-config.service.spec.ts +++ b/server/src/domain/system-config/system-config.service.spec.ts @@ -13,7 +13,7 @@ import { } from '@app/infra/entities'; import { BadRequestException } from '@nestjs/common'; import { newCommunicationRepositoryMock, newJobRepositoryMock, newSystemConfigRepositoryMock } from '@test'; -import { ICommunicationRepository } from '..'; +import { ICommunicationRepository } from '../communication'; import { IJobRepository, JobName, QueueName } from '../job'; import { SystemConfigValidator, defaults } from './system-config.core'; import { ISystemConfigRepository } from './system-config.repository'; diff --git a/server/src/domain/system-config/system-config.service.ts b/server/src/domain/system-config/system-config.service.ts index ece328ac43..6d8e7be337 100644 --- a/server/src/domain/system-config/system-config.service.ts +++ b/server/src/domain/system-config/system-config.service.ts @@ -24,7 +24,7 @@ export class SystemConfigService { @Inject(ICommunicationRepository) private communicationRepository: ICommunicationRepository, @Inject(IJobRepository) private jobRepository: IJobRepository, ) { - this.core = new SystemConfigCore(repository); + this.core = SystemConfigCore.create(repository); } get config$() { diff --git a/server/test/repositories/system-config.repository.mock.ts b/server/test/repositories/system-config.repository.mock.ts index 254f3bad23..44ad8f6306 100644 --- a/server/test/repositories/system-config.repository.mock.ts +++ b/server/test/repositories/system-config.repository.mock.ts @@ -1,6 +1,10 @@ -import { ISystemConfigRepository } from '@app/domain'; +import { ISystemConfigRepository, SystemConfigCore } from '@app/domain'; + +export const newSystemConfigRepositoryMock = (reset = true): jest.Mocked => { + if (reset) { + SystemConfigCore.reset(); + } -export const newSystemConfigRepositoryMock = (): jest.Mocked => { return { load: jest.fn().mockResolvedValue([]), readFile: jest.fn(),