diff --git a/ci/config.json.ci b/ci/config.json.ci index b5937068d..9679aa57c 100644 --- a/ci/config.json.ci +++ b/ci/config.json.ci @@ -188,5 +188,8 @@ "jobReassignMsgIndexToEvent": { "millisecondCrawl": 1000, "blocksPerCall": 100 + }, + "servicesManager": { + "healthCheckLimit": 100 } } diff --git a/config.json b/config.json index b64430ef3..01134d467 100644 --- a/config.json +++ b/config.json @@ -188,5 +188,8 @@ "jobReassignMsgIndexToEvent": { "millisecondCrawl": 1000, "blocksPerCall": 100 + }, + "servicesManager": { + "healthCheckLimit": 100 } } diff --git a/src/common/constant.ts b/src/common/constant.ts index d1b4ae16f..f389d323d 100644 --- a/src/common/constant.ts +++ b/src/common/constant.ts @@ -274,6 +274,14 @@ export const SERVICE = { key: 'CrawlIBCAppService', name: 'v1.CrawlIBCAppService', }, + ServicesManager: { + key: 'ServicesManager', + name: 'v1.ServicesManager', + HealthCheck: { + key: 'HealthCheck', + path: 'v1.ServicesManager.HealthCheck', + }, + }, HoroscopeHandlerService: { key: 'HoroscopeHandlerService', path: 'v1.HoroscopeHandlerService', diff --git a/src/services/api-gateways/api_gateway.service.ts b/src/services/api-gateways/api_gateway.service.ts index b59554c73..c9a2df478 100644 --- a/src/services/api-gateways/api_gateway.service.ts +++ b/src/services/api-gateways/api_gateway.service.ts @@ -26,6 +26,7 @@ import { bullBoardMixin } from '../../mixins/bullBoard/bullBoard.mixin'; 'v2.graphql.*', 'v2.statistics.getDashboardStatisticsByChainId', 'v2.statistics.getTopAccountsByChainId', + 'v1.services-manager.*', ], }, { diff --git a/src/services/api-gateways/services-manager.service.ts b/src/services/api-gateways/services-manager.service.ts new file mode 100644 index 000000000..bfbb78b31 --- /dev/null +++ b/src/services/api-gateways/services-manager.service.ts @@ -0,0 +1,49 @@ +import { Get, Service } from '@ourparentcenter/moleculer-decorators-extended'; +import { Context, ServiceBroker } from 'moleculer'; +import networks from '../../../network.json' assert { type: 'json' }; +import BaseService from '../../base/base.service'; + +@Service({ + name: 'services-manager', + version: 1, +}) +export default class ServicesManagerService extends BaseService { + public constructor(public broker: ServiceBroker) { + super(broker); + } + + @Get('/health-check', { + name: 'healthCheck', + params: { + chainid: { + type: 'string', + optional: false, + enum: networks.map((network) => network.chainId), + }, + jobNames: { + type: 'array', + optional: false, + items: 'string', + }, + }, + }) + async healthCheck( + ctx: Context< + { + chainid: string; + jobNames: string[]; + }, + Record + > + ) { + const selectedChain = networks.find( + (network) => network.chainId === ctx.params.chainid + ); + return this.broker.call( + `v1.ServicesManager.HealthCheck@${selectedChain?.moleculerNamespace}`, + { + jobNames: ctx.params.jobNames, + } + ); + } +} diff --git a/src/services/manager/services-manager.service.ts b/src/services/manager/services-manager.service.ts new file mode 100644 index 000000000..8d3a2ab4d --- /dev/null +++ b/src/services/manager/services-manager.service.ts @@ -0,0 +1,50 @@ +import { + Action, + Service, +} from '@ourparentcenter/moleculer-decorators-extended'; +import { Context, ServiceBroker } from 'moleculer'; +import config from '../../../config.json' assert { type: 'json' }; +import BullableService from '../../base/bullable.service'; +import { BULL_JOB_NAME, SERVICE } from '../../common'; +import { BlockCheckpoint } from '../../models'; + +@Service({ + name: SERVICE.V1.ServicesManager.key, + version: 1, +}) +export default class ServicesManagerService extends BullableService { + public constructor(public broker: ServiceBroker) { + super(broker); + } + + @Action({ + name: SERVICE.V1.ServicesManager.HealthCheck.key, + params: { + jobNames: { + type: 'array', + optional: false, + items: 'string', + }, + }, + }) + public async actionHealthCheck(ctx: Context<{ jobNames: string[] }>) { + const { jobNames } = ctx.params; + const result: Record = {}; + const jobBlock = await BlockCheckpoint.query() + .where('job_name', BULL_JOB_NAME.CRAWL_BLOCK) + .first() + .throwIfNotFound(); + const jobsHeight = await BlockCheckpoint.query().whereIn( + 'job_name', + jobNames + ); + jobsHeight.forEach((job) => { + Object.assign(result, { + [job.job_name]: + jobBlock.height - job.height < + config.servicesManager.healthCheckLimit, + }); + }); + return result; + } +}