From 17dfcedad60b136c1cf2713e38e86973e32af274 Mon Sep 17 00:00:00 2001 From: izzy Date: Wed, 3 Dec 2025 11:34:15 +0000 Subject: [PATCH] refactor: remove state repository --- server/src/app.module.ts | 2 - .../maintenance-ephemeral-state.repository.ts | 38 ------------ .../maintenance/maintenance-worker.service.ts | 58 ++++++++++++------- 3 files changed, 36 insertions(+), 62 deletions(-) delete mode 100644 server/src/maintenance/maintenance-ephemeral-state.repository.ts diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 25dab73ef3..f3f6ab74e7 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -10,7 +10,6 @@ import { IWorker } from 'src/constants'; import { controllers } from 'src/controllers'; import { ImmichWorker } from 'src/enum'; import { MaintenanceAuthGuard } from 'src/maintenance/maintenance-auth.guard'; -import { MaintenanceEphemeralStateRepository } from 'src/maintenance/maintenance-ephemeral-state.repository'; import { MaintenanceWebsocketRepository } from 'src/maintenance/maintenance-websocket.repository'; import { MaintenanceWorkerController } from 'src/maintenance/maintenance-worker.controller'; import { MaintenanceWorkerService } from 'src/maintenance/maintenance-worker.service'; @@ -113,7 +112,6 @@ export class ApiModule extends BaseModule {} SystemMetadataRepository, AppRepository, MaintenanceWebsocketRepository, - MaintenanceEphemeralStateRepository, MaintenanceWorkerService, ...commonMiddleware, { provide: APP_GUARD, useClass: MaintenanceAuthGuard }, diff --git a/server/src/maintenance/maintenance-ephemeral-state.repository.ts b/server/src/maintenance/maintenance-ephemeral-state.repository.ts deleted file mode 100644 index 0f45c30a22..0000000000 --- a/server/src/maintenance/maintenance-ephemeral-state.repository.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { MaintenanceStatusResponseDto } from 'src/dtos/maintenance.dto'; -import { MaintenanceAction } from 'src/enum'; - -@Injectable() -export class MaintenanceEphemeralStateRepository { - #secret: string = null!; - #state: MaintenanceStatusResponseDto = { - active: true, - action: MaintenanceAction.Start, - }; - - setSecret(secret: string) { - this.#secret = secret; - } - - getSecret(): string { - return this.#secret; - } - - setStatus(state: MaintenanceStatusResponseDto) { - this.#state = state; - } - - getStatus(): MaintenanceStatusResponseDto { - return this.#state; - } - - getPublicStatus(): MaintenanceStatusResponseDto { - const state = structuredClone(this.#state); - - if (state.error) { - state.error = 'Something went wrong, see logs!'; - } - - return state; - } -} diff --git a/server/src/maintenance/maintenance-worker.service.ts b/server/src/maintenance/maintenance-worker.service.ts index 626640020d..f6f91c8147 100644 --- a/server/src/maintenance/maintenance-worker.service.ts +++ b/server/src/maintenance/maintenance-worker.service.ts @@ -21,7 +21,6 @@ import { StorageFolder, SystemMetadataKey, } from 'src/enum'; -import { MaintenanceEphemeralStateRepository } from 'src/maintenance/maintenance-ephemeral-state.repository'; import { MaintenanceWebsocketRepository } from 'src/maintenance/maintenance-websocket.repository'; import { AppRepository } from 'src/repositories/app.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; @@ -46,13 +45,18 @@ import { getExternalDomain } from 'src/utils/misc'; */ @Injectable() export class MaintenanceWorkerService { + #secret: string = null!; + #status: MaintenanceStatusResponseDto = { + active: true, + action: MaintenanceAction.Start, + }; + constructor( protected logger: LoggingRepository, private appRepository: AppRepository, private configRepository: ConfigRepository, private systemMetadataRepository: SystemMetadataRepository, private maintenanceWebsocketRepository: MaintenanceWebsocketRepository, - private maintenanceEphemeralStateRepository: MaintenanceEphemeralStateRepository, private storageRepository: StorageRepository, private processRepository: ProcessRepository, private databaseRepository: DatabaseRepository, @@ -60,24 +64,26 @@ export class MaintenanceWorkerService { this.logger.setContext(this.constructor.name); } + mock(status: MaintenanceStatusResponseDto) { + this.#secret = 'secret'; + this.#status = status; + } + async init() { const state = (await this.systemMetadataRepository.get( SystemMetadataKey.MaintenanceMode, )) as MaintenanceModeState & { isMaintenanceMode: true }; - this.maintenanceEphemeralStateRepository.setSecret(state.secret); - this.maintenanceEphemeralStateRepository.setStatus({ + this.#secret = state.secret; + this.#status = { active: true, action: state.action.action, - }); + }; StorageCore.setMediaLocation(this.detectMediaLocation()); this.maintenanceWebsocketRepository.setAuthFn(async (client) => this.authenticate(client.request.headers)); - - this.maintenanceWebsocketRepository.setStatusUpdateFn((status) => - this.maintenanceEphemeralStateRepository.setStatus(status), - ); + this.maintenanceWebsocketRepository.setStatusUpdateFn((status) => (this.#status = status)); await this.logSecret(); void this.runAction(state.action); @@ -218,15 +224,25 @@ export class MaintenanceWorkerService { }; } + private getStatus(): MaintenanceStatusResponseDto { + return this.#status; + } + + private getPublicStatus(): MaintenanceStatusResponseDto { + const state = structuredClone(this.#status); + + if (state.error) { + state.error = 'Something went wrong, see logs!'; + } + + return state; + } + setStatus(status: MaintenanceStatusResponseDto): void { - this.maintenanceEphemeralStateRepository.setStatus(status); + this.#status = status; this.maintenanceWebsocketRepository.serverSend('MaintenanceStatus', status); this.maintenanceWebsocketRepository.clientSend('MaintenanceStatusV1', 'private', status); - this.maintenanceWebsocketRepository.clientSend( - 'MaintenanceStatusV1', - 'public', - this.maintenanceEphemeralStateRepository.getPublicStatus(), - ); + this.maintenanceWebsocketRepository.clientSend('MaintenanceStatusV1', 'public', this.getPublicStatus()); } async logSecret(): Promise { @@ -238,7 +254,7 @@ export class MaintenanceWorkerService { { username: 'immich-admin', }, - this.maintenanceEphemeralStateRepository.getSecret(), + this.#secret, ); this.logger.log(`\n\n🚧 Immich is in maintenance mode, you can log in using the following URL:\n${url}\n`); @@ -252,9 +268,9 @@ export class MaintenanceWorkerService { async status(potentiallyJwt?: string): Promise { try { await this.login(potentiallyJwt); - return this.maintenanceEphemeralStateRepository.getStatus(); + return this.getStatus(); } catch { - return this.maintenanceEphemeralStateRepository.getPublicStatus(); + return this.getPublicStatus(); } } @@ -267,10 +283,8 @@ export class MaintenanceWorkerService { throw new UnauthorizedException('Missing JWT Token'); } - const secret = this.maintenanceEphemeralStateRepository.getSecret(); - try { - const result = await jwtVerify(jwt, new TextEncoder().encode(secret)); + const result = await jwtVerify(jwt, new TextEncoder().encode(this.#secret)); return result.payload; } catch { throw new UnauthorizedException('Invalid JWT Token'); @@ -312,7 +326,7 @@ export class MaintenanceWorkerService { await this.systemMetadataRepository.set(SystemMetadataKey.MaintenanceMode, { isMaintenanceMode: true, - secret: this.maintenanceEphemeralStateRepository.getSecret(), + secret: this.#secret, action: { action: MaintenanceAction.Start, },