chore: use configured media location

refactor: move detect location to common util
This commit is contained in:
izzy 2026-06-17 11:09:10 +01:00
parent 88048548f6
commit 71207ec7dc
No known key found for this signature in database
4 changed files with 32 additions and 45 deletions

View file

@ -7,6 +7,8 @@ import { ClsModule } from 'nestjs-cls';
import { KyselyModule } from 'nestjs-kysely';
import { OpenTelemetryModule } from 'nestjs-otel';
import { ZodSerializerInterceptor, ZodValidationPipe } from 'nestjs-zod';
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import { commandsAndQuestions } from 'src/commands';
import { IWorker } from 'src/constants';
import { controllers } from 'src/controllers';
@ -40,6 +42,7 @@ import { DatabaseBackupService } from 'src/services/database-backup.service';
import { QueueService } from 'src/services/queue.service';
import { getKyselyConfig } from 'src/utils/database';
import { configureUserAgent } from 'src/utils/fetch';
import { detectMediaLocation } from 'src/utils/storage';
const common = [...repositories, ...services, GlobalExceptionFilter];
@ -54,10 +57,11 @@ const commonMiddleware = [
const apiMiddleware = [FileUploadInterceptor, ...commonMiddleware, { provide: APP_GUARD, useClass: AuthGuard }];
const configRepository = new ConfigRepository();
const { bull, cls, database, /* environment, */ otel } = configRepository.getEnv();
const { bull, cls, database, /* environment, */ otel, storage } = configRepository.getEnv();
const isYuccaDevelopmentMode = true; // TODO[YUCCA]: for testing
// const isYuccaDevelopmentMode = environment === ImmichEnvironment.Development;
const isYuccaDevelopmentMode = true; // TODO[YUCCA]: for testing
const yuccaStatePath = join(detectMediaLocation(storage.mediaLocation, existsSync), 'yucca');
const commonImports = [
ClsModule.forRoot(cls.config),
@ -112,7 +116,7 @@ export class BaseModule implements OnModuleInit, OnModuleDestroy {
ScheduleModule.forRoot(),
OrchestrationApiModule.forRoot({
yuccaProductionApi: 'https://staging.fubar.computer', // TODO[YUCCA]: remove to load from futo.cloud/.well-known
statePath: '/data/yucca', // TODO[YUCCA]: point to {immich_data_location}/yucca
statePath: yuccaStatePath,
requireWsAuth: true,
requireLock: true,
developmentMode: isYuccaDevelopmentMode,
@ -128,7 +132,7 @@ export class ApiModule extends BaseModule {}
...commonImports,
OrchestrationApiModule.forRoot({
yuccaProductionApi: 'https://staging.fubar.computer', // TODO[YUCCA]: remove to load from futo.cloud/.well-known
statePath: '/data/yucca', // TODO[YUCCA]: point to {immich_data_location}/yucca
statePath: yuccaStatePath,
externalBaseUrl: 'https://my.immich.app',
requireWsAuth: true,
requireLock: true,

View file

@ -33,6 +33,7 @@ import { MaintenanceModeState } from 'src/types';
import { getConfig } from 'src/utils/config';
import { createMaintenanceLoginUrl, detectPriorInstall } from 'src/utils/maintenance';
import { getExternalDomain } from 'src/utils/misc';
import { detectMediaLocation } from 'src/utils/storage';
/**
* This service is available inside of maintenance mode to manage maintenance mode
@ -168,30 +169,9 @@ export class MaintenanceWorkerService {
};
}
/**
* {@link _StorageService.detectMediaLocation}
*/
detectMediaLocation(): string {
const envData = this.configRepository.getEnv();
if (envData.storage.mediaLocation) {
return envData.storage.mediaLocation;
}
const targets: string[] = [];
const candidates = ['/data', '/usr/src/app/upload'];
for (const candidate of candidates) {
const exists = this.storageRepository.existsSync(candidate);
if (exists) {
targets.push(candidate);
}
}
if (targets.length === 1) {
return targets[0];
}
return '/usr/src/app/upload';
return detectMediaLocation(envData.storage.mediaLocation, (path) => this.storageRepository.existsSync(path));
}
private get secret() {

View file

@ -15,6 +15,7 @@ import {
import { BaseService } from 'src/services/base.service';
import { JobOf, SystemFlags } from 'src/types';
import { ImmichStartupError } from 'src/utils/misc';
import { detectMediaLocation } from 'src/utils/storage';
const docsMessage = `Please see https://docs.immich.app/administration/system-integrity#folder-checks for more information.`;
@ -22,25 +23,7 @@ const docsMessage = `Please see https://docs.immich.app/administration/system-in
export class StorageService extends BaseService {
private detectMediaLocation(): string {
const envData = this.configRepository.getEnv();
if (envData.storage.mediaLocation) {
return envData.storage.mediaLocation;
}
const targets: string[] = [];
const candidates = ['/data', '/usr/src/app/upload'];
for (const candidate of candidates) {
const exists = this.storageRepository.existsSync(candidate);
if (exists) {
targets.push(candidate);
}
}
if (targets.length === 1) {
return targets[0];
}
return '/usr/src/app/upload';
return detectMediaLocation(envData.storage.mediaLocation, (path) => this.storageRepository.existsSync(path));
}
@OnEvent({ name: 'AppBootstrap', priority: BootstrapEventPriority.StorageService })

View file

@ -0,0 +1,20 @@
export const detectMediaLocation = (mediaLocation: string | undefined, exists: (path: string) => boolean): string => {
if (mediaLocation) {
return mediaLocation;
}
const targets: string[] = [];
const candidates = ['/data', '/usr/src/app/upload'];
for (const candidate of candidates) {
if (exists(candidate)) {
targets.push(candidate);
}
}
if (targets.length === 1) {
return targets[0];
}
return '/usr/src/app/upload';
};