mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-13 12:25:53 +00:00
* fix(maintenance): prevent CLI hanging on occassion fix(maintenance): always ack messages fix(maintenance): ensure Redis is connected first * chore(maintenance): validate app restart responses * chore: mock the app restart callback * fix: ack may not exist depending on caller * refactor: move one shot into app.repository * fix: send correct state in one shot * chore: log restart event
57 lines
2 KiB
TypeScript
57 lines
2 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { OnEvent } from 'src/decorators';
|
|
import { MaintenanceAuthDto } from 'src/dtos/maintenance.dto';
|
|
import { SystemMetadataKey } from 'src/enum';
|
|
import { ArgOf } from 'src/repositories/event.repository';
|
|
import { BaseService } from 'src/services/base.service';
|
|
import { MaintenanceModeState } from 'src/types';
|
|
import { createMaintenanceLoginUrl, generateMaintenanceSecret, signMaintenanceJwt } from 'src/utils/maintenance';
|
|
import { getExternalDomain } from 'src/utils/misc';
|
|
|
|
/**
|
|
* This service is available outside of maintenance mode to manage maintenance mode
|
|
*/
|
|
@Injectable()
|
|
export class MaintenanceService extends BaseService {
|
|
getMaintenanceMode(): Promise<MaintenanceModeState> {
|
|
return this.systemMetadataRepository
|
|
.get(SystemMetadataKey.MaintenanceMode)
|
|
.then((state) => state ?? { isMaintenanceMode: false });
|
|
}
|
|
|
|
async startMaintenance(username: string): Promise<{ jwt: string }> {
|
|
const secret = generateMaintenanceSecret();
|
|
await this.systemMetadataRepository.set(SystemMetadataKey.MaintenanceMode, { isMaintenanceMode: true, secret });
|
|
await this.eventRepository.emit('AppRestart', { isMaintenanceMode: true });
|
|
|
|
return {
|
|
jwt: await signMaintenanceJwt(secret, {
|
|
username,
|
|
}),
|
|
};
|
|
}
|
|
|
|
@OnEvent({ name: 'AppRestart', server: true })
|
|
onRestart(event: ArgOf<'AppRestart'>, ack?: (ok: 'ok') => void): void {
|
|
this.logger.log(`Restarting due to event... ${JSON.stringify(event)}`);
|
|
|
|
ack?.('ok');
|
|
this.appRepository.exitApp();
|
|
}
|
|
|
|
async createLoginUrl(auth: MaintenanceAuthDto, secret?: string): Promise<string> {
|
|
const { server } = await this.getConfig({ withCache: true });
|
|
const baseUrl = getExternalDomain(server);
|
|
|
|
if (!secret) {
|
|
const state = await this.getMaintenanceMode();
|
|
if (!state.isMaintenanceMode) {
|
|
throw new Error('Not in maintenance mode');
|
|
}
|
|
|
|
secret = state.secret;
|
|
}
|
|
|
|
return await createMaintenanceLoginUrl(baseUrl, auth, secret);
|
|
}
|
|
}
|