diff --git a/CHANGELOG.md b/CHANGELOG.md index 546e67dfd..ddf8511b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Added health check endpoints for data enhancers + ## 1.303.0 - 2023-08-23 ### Added diff --git a/apps/api/src/app/health/health.controller.ts b/apps/api/src/app/health/health.controller.ts index d9af97981..3c8c0ef56 100644 --- a/apps/api/src/app/health/health.controller.ts +++ b/apps/api/src/app/health/health.controller.ts @@ -18,6 +18,20 @@ export class HealthController { @Get() public async getHealth() {} + @Get('data-enhancer/:name') + public async getHealthOfDataEnhancer(@Param('name') name: string) { + const hasResponse = await this.healthService.hasResponseFromDataEnhancer( + name + ); + + if (hasResponse !== true) { + throw new HttpException( + getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE), + StatusCodes.SERVICE_UNAVAILABLE + ); + } + } + @Get('data-provider/:dataSource') @UseInterceptors(TransformDataSourceInRequestInterceptor) public async getHealthOfDataProvider( diff --git a/apps/api/src/app/health/health.module.ts b/apps/api/src/app/health/health.module.ts index 1c5292027..b6952c3b5 100644 --- a/apps/api/src/app/health/health.module.ts +++ b/apps/api/src/app/health/health.module.ts @@ -1,4 +1,5 @@ import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { DataEnhancerModule } from '@ghostfolio/api/services/data-provider/data-enhancer/data-enhancer.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { Module } from '@nestjs/common'; @@ -7,7 +8,7 @@ import { HealthService } from './health.service'; @Module({ controllers: [HealthController], - imports: [ConfigurationModule, DataProviderModule], + imports: [ConfigurationModule, DataEnhancerModule, DataProviderModule], providers: [HealthService] }) export class HealthModule {} diff --git a/apps/api/src/app/health/health.service.ts b/apps/api/src/app/health/health.service.ts index afbcc0a74..8fac2dde9 100644 --- a/apps/api/src/app/health/health.service.ts +++ b/apps/api/src/app/health/health.service.ts @@ -1,3 +1,4 @@ +import { DataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/data-enhancer.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { Injectable } from '@nestjs/common'; import { DataSource } from '@prisma/client'; @@ -5,9 +6,14 @@ import { DataSource } from '@prisma/client'; @Injectable() export class HealthService { public constructor( + private readonly dataEnhancerService: DataEnhancerService, private readonly dataProviderService: DataProviderService ) {} + public async hasResponseFromDataEnhancer(aName: string) { + return this.dataEnhancerService.enhance(aName); + } + public async hasResponseFromDataProvider(aDataSource: DataSource) { return this.dataProviderService.checkQuote(aDataSource); } diff --git a/apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts b/apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts index a658ef448..069309508 100644 --- a/apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts +++ b/apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts @@ -4,14 +4,18 @@ import { TrackinsightDataEnhancerService } from '@ghostfolio/api/services/data-p import { YahooFinanceDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service'; import { Module } from '@nestjs/common'; +import { DataEnhancerService } from './data-enhancer.service'; + @Module({ exports: [ - 'DataEnhancers', + DataEnhancerService, TrackinsightDataEnhancerService, - YahooFinanceDataEnhancerService + YahooFinanceDataEnhancerService, + 'DataEnhancers' ], imports: [ConfigurationModule, CryptocurrencyModule], providers: [ + DataEnhancerService, TrackinsightDataEnhancerService, YahooFinanceDataEnhancerService, { diff --git a/apps/api/src/services/data-provider/data-enhancer/data-enhancer.service.ts b/apps/api/src/services/data-provider/data-enhancer/data-enhancer.service.ts new file mode 100644 index 000000000..e5038c7c6 --- /dev/null +++ b/apps/api/src/services/data-provider/data-enhancer/data-enhancer.service.ts @@ -0,0 +1,44 @@ +import { DataEnhancerInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-enhancer.interface'; +import { HttpException, Inject, Injectable } from '@nestjs/common'; +import { Prisma } from '@prisma/client'; +import { StatusCodes, getReasonPhrase } from 'http-status-codes'; + +@Injectable() +export class DataEnhancerService { + public constructor( + @Inject('DataEnhancers') + private readonly dataEnhancers: DataEnhancerInterface[] + ) {} + + public async enhance(aName: string) { + const dataEnhancer = this.dataEnhancers.find((dataEnhancer) => { + return dataEnhancer.getName() === aName; + }); + + if (!dataEnhancer) { + throw new HttpException( + getReasonPhrase(StatusCodes.NOT_FOUND), + StatusCodes.NOT_FOUND + ); + } + + try { + const assetProfile = await dataEnhancer.enhance({ + response: { + assetClass: 'EQUITY', + assetSubClass: 'ETF' + }, + symbol: dataEnhancer.getTestSymbol() + }); + + if ( + (assetProfile.countries as unknown as Prisma.JsonArray)?.length > 0 && + (assetProfile.sectors as unknown as Prisma.JsonArray)?.length > 0 + ) { + return true; + } + } catch {} + + return false; + } +} diff --git a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts index 2c9f1b7a8..ee81ef591 100644 --- a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts @@ -126,4 +126,8 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { public getName() { return 'TRACKINSIGHT'; } + + public getTestSymbol() { + return 'QQQ'; + } } diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts index 3ad69646b..54145a8b4 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts @@ -234,6 +234,10 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { return DataSource.YAHOO; } + public getTestSymbol() { + return 'AAPL'; + } + public parseAssetClass({ quoteType, shortName diff --git a/apps/api/src/services/data-provider/interfaces/data-enhancer.interface.ts b/apps/api/src/services/data-provider/interfaces/data-enhancer.interface.ts index 4e5ce8cba..9c6db9196 100644 --- a/apps/api/src/services/data-provider/interfaces/data-enhancer.interface.ts +++ b/apps/api/src/services/data-provider/interfaces/data-enhancer.interface.ts @@ -10,4 +10,6 @@ export interface DataEnhancerInterface { }): Promise>; getName(): string; + + getTestSymbol(): string; }