import { AiService } from '@ghostfolio/api/app/endpoints/ai/ai.service'; import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { AiServiceHealthResponse, DataEnhancerHealthResponse, DataProviderHealthResponse } from '@ghostfolio/common/interfaces'; import { Controller, Get, HttpException, HttpStatus, Logger, Param, Res, UseInterceptors } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import { Response } from 'express'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { HealthService } from './health.service'; @Controller('health') export class HealthController { private readonly logger = new Logger(HealthController.name); public constructor( private readonly aiService: AiService, private readonly healthService: HealthService ) {} @Get() public async getHealth(@Res() response: Response) { const databaseServiceHealthy = await this.healthService.isDatabaseHealthy(); const redisCacheServiceHealthy = await this.healthService.isRedisCacheHealthy(); if (databaseServiceHealthy && redisCacheServiceHealthy) { return response .status(HttpStatus.OK) .json({ status: getReasonPhrase(StatusCodes.OK) }); } else { return response .status(HttpStatus.SERVICE_UNAVAILABLE) .json({ status: getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE) }); } } @Get('ai') public async getHealthOfAiService( @Res() response: Response ): Promise> { try { const { text } = await this.aiService.generateText({ prompt: `Reply with the word "OK" and nothing else.` }); if (text === 'OK') { return response .status(HttpStatus.OK) .json({ status: getReasonPhrase(StatusCodes.OK) }); } } catch (error) { this.logger.error(error); } return response .status(HttpStatus.SERVICE_UNAVAILABLE) .json({ status: getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE) }); } @Get('data-enhancer/:name') public async getHealthOfDataEnhancer( @Param('name') name: string, @Res() response: Response ): Promise> { const hasResponse = await this.healthService.hasResponseFromDataEnhancer(name); if (hasResponse) { return response.status(HttpStatus.OK).json({ status: getReasonPhrase(StatusCodes.OK) }); } else { return response .status(HttpStatus.SERVICE_UNAVAILABLE) .json({ status: getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE) }); } } @Get('data-provider/:dataSource') @UseInterceptors(TransformDataSourceInRequestInterceptor) public async getHealthOfDataProvider( @Param('dataSource') dataSource: DataSource, @Res() response: Response ): Promise> { if (!DataSource[dataSource]) { throw new HttpException( getReasonPhrase(StatusCodes.NOT_FOUND), StatusCodes.NOT_FOUND ); } const hasResponse = await this.healthService.hasResponseFromDataProvider(dataSource); if (hasResponse) { return response .status(HttpStatus.OK) .json({ status: getReasonPhrase(StatusCodes.OK) }); } else { return response .status(HttpStatus.SERVICE_UNAVAILABLE) .json({ status: getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE) }); } } }