refactor: config repository (#15495)

* refactor: access repository

* refactor: config repository
This commit is contained in:
Jason Rasmussen
2025-01-21 13:13:09 -05:00
committed by GitHub
parent 332a865ce6
commit 9a27a99cab
35 changed files with 150 additions and 171 deletions

View File

@@ -4,10 +4,15 @@ import { InjectKysely } from 'nestjs-kysely';
import { DB } from 'src/db';
import { DummyValue, GenerateSql } from 'src/decorators';
import { DatabaseAction, EntityType } from 'src/enum';
import { AuditSearch, IAuditRepository } from 'src/interfaces/audit.interface';
export interface AuditSearch {
action?: DatabaseAction;
entityType?: EntityType;
userIds: string[];
}
@Injectable()
export class AuditRepository implements IAuditRepository {
export class AuditRepository {
constructor(@InjectKysely() private db: Kysely<DB>) {}
@GenerateSql({

View File

@@ -1,19 +1,106 @@
import { RegisterQueueOptions } from '@nestjs/bullmq';
import { Inject, Injectable, Optional } from '@nestjs/common';
import { QueueOptions } from 'bullmq';
import { plainToInstance } from 'class-transformer';
import { validateSync } from 'class-validator';
import { Request, Response } from 'express';
import { RedisOptions } from 'ioredis';
import { KyselyConfig } from 'kysely';
import { PostgresJSDialect } from 'kysely-postgres-js';
import { CLS_ID } from 'nestjs-cls';
import { CLS_ID, ClsModuleOptions } from 'nestjs-cls';
import { OpenTelemetryModuleOptions } from 'nestjs-otel/lib/interfaces';
import { join, resolve } from 'node:path';
import postgres, { Notice } from 'postgres';
import { citiesFile, excludePaths, IWorker } from 'src/constants';
import { Telemetry } from 'src/decorators';
import { EnvDto } from 'src/dtos/env.dto';
import { ImmichEnvironment, ImmichHeader, ImmichTelemetry, ImmichWorker } from 'src/enum';
import { EnvData, IConfigRepository } from 'src/interfaces/config.interface';
import { DatabaseExtension } from 'src/interfaces/database.interface';
import { ImmichEnvironment, ImmichHeader, ImmichTelemetry, ImmichWorker, LogLevel } from 'src/enum';
import { DatabaseConnectionParams, DatabaseExtension, VectorExtension } from 'src/interfaces/database.interface';
import { QueueName } from 'src/interfaces/job.interface';
import { setDifference } from 'src/utils/set';
import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js';
export interface EnvData {
host?: string;
port: number;
environment: ImmichEnvironment;
configFile?: string;
logLevel?: LogLevel;
buildMetadata: {
build?: string;
buildUrl?: string;
buildImage?: string;
buildImageUrl?: string;
repository?: string;
repositoryUrl?: string;
sourceRef?: string;
sourceCommit?: string;
sourceUrl?: string;
thirdPartySourceUrl?: string;
thirdPartyBugFeatureUrl?: string;
thirdPartyDocumentationUrl?: string;
thirdPartySupportUrl?: string;
};
bull: {
config: QueueOptions;
queues: RegisterQueueOptions[];
};
cls: {
config: ClsModuleOptions;
};
database: {
config: { typeorm: PostgresConnectionOptions & DatabaseConnectionParams; kysely: KyselyConfig };
skipMigrations: boolean;
vectorExtension: VectorExtension;
};
licensePublicKey: {
client: string;
server: string;
};
network: {
trustedProxies: string[];
};
otel: OpenTelemetryModuleOptions;
resourcePaths: {
lockFile: string;
geodata: {
dateFile: string;
admin1: string;
admin2: string;
cities500: string;
naturalEarthCountriesPath: string;
};
web: {
root: string;
indexHtml: string;
};
};
redis: RedisOptions;
telemetry: {
apiPort: number;
microservicesPort: number;
metrics: Set<ImmichTelemetry>;
};
storage: {
ignoreMountCheckErrors: boolean;
};
workers: ImmichWorker[];
noColor: boolean;
nodeVersion?: string;
}
const productionKeys = {
client:
@@ -269,10 +356,10 @@ let cached: EnvData | undefined;
@Injectable()
@Telemetry({ enabled: false })
export class ConfigRepository implements IConfigRepository {
export class ConfigRepository {
constructor(@Inject(IWorker) @Optional() private worker?: ImmichWorker) {}
getEnv(): EnvData {
getEnv() {
if (!cached) {
cached = getEnv();
}

View File

@@ -6,7 +6,6 @@ import { InjectKysely } from 'nestjs-kysely';
import semver from 'semver';
import { POSTGRES_VERSION_RANGE, VECTOR_VERSION_RANGE, VECTORS_VERSION_RANGE } from 'src/constants';
import { DB } from 'src/db';
import { IConfigRepository } from 'src/interfaces/config.interface';
import {
DatabaseExtension,
DatabaseLock,
@@ -18,6 +17,7 @@ import {
VectorUpdateResult,
} from 'src/interfaces/database.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { ConfigRepository } from 'src/repositories/config.repository';
import { UPSERT_COLUMNS } from 'src/utils/database';
import { isValidInteger } from 'src/validation';
import { DataSource, EntityManager, EntityMetadata, QueryRunner } from 'typeorm';
@@ -31,7 +31,7 @@ export class DatabaseRepository implements IDatabaseRepository {
@InjectKysely() private db: Kysely<DB>,
@InjectDataSource() private dataSource: DataSource,
@Inject(ILoggerRepository) private logger: ILoggerRepository,
@Inject(IConfigRepository) configRepository: IConfigRepository,
configRepository: ConfigRepository,
) {
this.vectorExtension = configRepository.getEnv().database.vectorExtension;
this.logger.setContext(DatabaseRepository.name);

View File

@@ -12,7 +12,6 @@ import _ from 'lodash';
import { Server, Socket } from 'socket.io';
import { EventConfig } from 'src/decorators';
import { ImmichWorker, MetadataKey } from 'src/enum';
import { IConfigRepository } from 'src/interfaces/config.interface';
import {
ArgsOf,
ClientEventMap,
@@ -52,7 +51,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect
constructor(
private moduleRef: ModuleRef,
@Inject(IConfigRepository) private configRepository: ConfigRepository,
private configRepository: ConfigRepository,
@Inject(ILoggerRepository) private logger: ILoggerRepository,
) {
this.logger.setContext(EventRepository.name);

View File

@@ -1,8 +1,6 @@
import { IAlbumUserRepository } from 'src/interfaces/album-user.interface';
import { IAlbumRepository } from 'src/interfaces/album.interface';
import { IAssetRepository } from 'src/interfaces/asset.interface';
import { IAuditRepository } from 'src/interfaces/audit.interface';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { ICronRepository } from 'src/interfaces/cron.interface';
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
import { IDatabaseRepository } from 'src/interfaces/database.interface';
@@ -78,15 +76,15 @@ export const repositories = [
//
AccessRepository,
ActivityRepository,
AuditRepository,
ApiKeyRepository,
ConfigRepository,
];
export const providers = [
{ provide: IAlbumRepository, useClass: AlbumRepository },
{ provide: IAlbumUserRepository, useClass: AlbumUserRepository },
{ provide: IAssetRepository, useClass: AssetRepository },
{ provide: IAuditRepository, useClass: AuditRepository },
{ provide: IConfigRepository, useClass: ConfigRepository },
{ provide: ICronRepository, useClass: CronRepository },
{ provide: ICryptoRepository, useClass: CryptoRepository },
{ provide: IDatabaseRepository, useClass: DatabaseRepository },

View File

@@ -1,13 +1,11 @@
import { getQueueToken } from '@nestjs/bullmq';
import { Inject, Injectable } from '@nestjs/common';
import { ModuleRef, Reflector } from '@nestjs/core';
import { SchedulerRegistry } from '@nestjs/schedule';
import { JobsOptions, Queue, Worker } from 'bullmq';
import { ClassConstructor } from 'class-transformer';
import { setTimeout } from 'node:timers/promises';
import { JobConfig } from 'src/decorators';
import { MetadataKey } from 'src/enum';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { IEventRepository } from 'src/interfaces/event.interface';
import {
IEntityJob,
@@ -22,6 +20,7 @@ import {
QueueStatus,
} from 'src/interfaces/job.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { ConfigRepository } from 'src/repositories/config.repository';
import { getKeyByValue, getMethodNames, ImmichStartupError } from 'src/utils/misc';
type JobMapItem = {
@@ -38,8 +37,7 @@ export class JobRepository implements IJobRepository {
constructor(
private moduleRef: ModuleRef,
private schedulerRegistry: SchedulerRegistry,
@Inject(IConfigRepository) private configRepository: IConfigRepository,
private configRepository: ConfigRepository,
@Inject(IEventRepository) private eventRepository: IEventRepository,
@Inject(ILoggerRepository) private logger: ILoggerRepository,
) {

View File

@@ -1,7 +1,7 @@
import { ClsService } from 'nestjs-cls';
import { ImmichWorker } from 'src/enum';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { LoggerRepository } from 'src/repositories/logger.repository';
import { IConfigRepository } from 'src/types';
import { mockEnvData, newConfigRepositoryMock } from 'test/repositories/config.repository.mock';
import { Mocked } from 'vitest';

View File

@@ -1,10 +1,10 @@
import { ConsoleLogger, Inject, Injectable, Scope } from '@nestjs/common';
import { ConsoleLogger, Injectable, Scope } from '@nestjs/common';
import { isLogLevelEnabled } from '@nestjs/common/services/utils/is-log-level-enabled.util';
import { ClsService } from 'nestjs-cls';
import { Telemetry } from 'src/decorators';
import { LogLevel } from 'src/enum';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { ConfigRepository } from 'src/repositories/config.repository';
const LOG_LEVELS = [LogLevel.VERBOSE, LogLevel.DEBUG, LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL];
@@ -25,7 +25,7 @@ export class LoggerRepository extends ConsoleLogger implements ILoggerRepository
constructor(
private cls: ClsService,
@Inject(IConfigRepository) configRepository: IConfigRepository,
configRepository: ConfigRepository,
) {
super(LoggerRepository.name);

View File

@@ -11,7 +11,6 @@ import { DB, GeodataPlaces, NaturalearthCountries } from 'src/db';
import { AssetEntity, withExif } from 'src/entities/asset.entity';
import { NaturalEarthCountriesTempEntity } from 'src/entities/natural-earth-countries.entity';
import { LogLevel, SystemMetadataKey } from 'src/enum';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface';
import {
GeoPoint,
@@ -21,6 +20,7 @@ import {
ReverseGeocodeResult,
} from 'src/interfaces/map.interface';
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
import { ConfigRepository } from 'src/repositories/config.repository';
interface MapDB extends DB {
geodata_places_tmp: GeodataPlaces;
@@ -30,7 +30,7 @@ interface MapDB extends DB {
@Injectable()
export class MapRepository implements IMapRepository {
constructor(
@Inject(IConfigRepository) private configRepository: IConfigRepository,
private configRepository: ConfigRepository,
@Inject(ISystemMetadataRepository) private metadataRepository: ISystemMetadataRepository,
@Inject(ILoggerRepository) private logger: ILoggerRepository,
@InjectKysely() private db: Kysely<MapDB>,

View File

@@ -4,9 +4,9 @@ import { exec as execCallback } from 'node:child_process';
import { readFile } from 'node:fs/promises';
import { promisify } from 'node:util';
import sharp from 'sharp';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { GitHubRelease, IServerInfoRepository, ServerBuildVersions } from 'src/interfaces/server-info.interface';
import { ConfigRepository } from 'src/repositories/config.repository';
const exec = promisify(execCallback);
const maybeFirstLine = async (command: string): Promise<string> => {
@@ -36,7 +36,7 @@ const getLockfileVersion = (name: string, lockfile?: BuildLockfile) => {
@Injectable()
export class ServerInfoRepository implements IServerInfoRepository {
constructor(
@Inject(IConfigRepository) private configRepository: IConfigRepository,
private configRepository: ConfigRepository,
@Inject(ILoggerRepository) private logger: ILoggerRepository,
) {
this.logger.setContext(ServerInfoRepository.name);

View File

@@ -15,9 +15,9 @@ import { MetricService } from 'nestjs-otel';
import { copyMetadataFromFunctionToFunction } from 'nestjs-otel/lib/opentelemetry.utils';
import { serverVersion } from 'src/constants';
import { ImmichTelemetry, MetadataKey } from 'src/enum';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { IMetricGroupRepository, ITelemetryRepository, MetricGroupOptions } from 'src/interfaces/telemetry.interface';
import { ConfigRepository } from 'src/repositories/config.repository';
class MetricGroupRepository implements IMetricGroupRepository {
private enabled = false;
@@ -95,7 +95,7 @@ export class TelemetryRepository implements ITelemetryRepository {
constructor(
private metricService: MetricService,
private reflect: Reflector,
@Inject(IConfigRepository) private configRepository: IConfigRepository,
private configRepository: ConfigRepository,
@Inject(ILoggerRepository) private logger: ILoggerRepository,
) {
const { telemetry } = this.configRepository.getEnv();