diff --git a/src/common/utils.ts b/src/common/utils.ts index f592234..d7ad0bd 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -1,34 +1,52 @@ -import { DependencyContainer, FactoryFunction } from 'tsyringe'; +import { DependencyContainer } from 'tsyringe'; import { Logger } from '@map-colonies/js-logger'; +import { HealthCheck } from '@godaddy/terminus'; import { RedisClient } from '../redis/index'; import { SERVICES } from './constants'; -export const healthCheckFactory: FactoryFunction = (container: DependencyContainer): void => { - const logger = container.resolve(SERVICES.LOGGER); - const geocodingRedis = container.resolve(SERVICES.GEOCODING_REDIS); - const ttlRedis = container.resolve(SERVICES.TTL_REDIS); +export const healthCheckFactory = (container: DependencyContainer): HealthCheck => { + return async (): Promise => { + const logger = container.resolve(SERVICES.LOGGER); + const geocodingRedis = container.resolve(SERVICES.GEOCODING_REDIS); + const ttlRedis = container.resolve(SERVICES.TTL_REDIS); - geocodingRedis - .ping() - .then(() => { - return; - }) - .catch((error: Error) => { - logger.error({ - message: `Healthcheck failed for GeocodingRedis.`, - error, - }); - }); + const promises: Promise[] = []; + + promises.push( + new Promise((resolve, reject) => { + geocodingRedis + .ping() + .then(() => { + resolve('Healthcheck passed for GeocodingRedis connection'); + }) + .catch((error: Error) => { + reject({ + msg: `Healthcheck failed for GeocodingRedis.`, + error, + }); + }); + }) + ); + promises.push( + new Promise((resolve, reject) => { + ttlRedis + .ping() + .then(() => { + resolve('Healthcheck passed for TTLRedis connection'); + }) + .catch((error: Error) => { + reject({ + msg: `Healthcheck failed for TTLRedis.`, + error, + }); + }); + }) + ); - ttlRedis - .ping() - .then(() => { - return; - }) - .catch((error: Error) => { - logger.error({ - message: `Healthcheck failed for GeocodingRedis.`, - error, - }); + await Promise.allSettled(promises).then((results) => { + results.forEach((msg) => logger.debug({ msg })); }); + + return Promise.resolve(); + }; }; diff --git a/src/containerConfig.ts b/src/containerConfig.ts index 675945e..b99a215 100644 --- a/src/containerConfig.ts +++ b/src/containerConfig.ts @@ -2,17 +2,17 @@ import config from 'config'; import { Producer } from 'kafkajs'; import { getOtelMixin } from '@map-colonies/telemetry'; import { trace, metrics as OtelMetrics } from '@opentelemetry/api'; +import { HealthCheck } from '@godaddy/terminus'; import { DependencyContainer } from 'tsyringe/dist/typings/types'; import jsLogger, { LoggerOptions } from '@map-colonies/js-logger'; import { CleanupRegistry } from '@map-colonies/cleanup-registry'; import { Metrics } from '@map-colonies/telemetry'; import { instancePerContainerCachingFactory } from 'tsyringe'; -import { createClient } from 'redis'; import { CLEANUP_REGISTRY, HEALTHCHECK, ON_SIGNAL, REDIS_CLIENT_FACTORY, REDIS_SUB, SERVICES, SERVICE_NAME } from './common/constants'; import { tracing } from './common/tracing'; import { feedbackRouterFactory, FEEDBACK_ROUTER_SYMBOL } from './feedback/routes/feedbackRouter'; import { InjectionObject, registerDependencies } from './common/dependencyRegistration'; -import { RedisClient, RedisClientFactory } from './redis'; +import { RedisClientFactory } from './redis'; import { kafkaClientFactory } from './kafka'; import { redisSubscribe } from './redis/subscribe'; import { healthCheckFactory } from './common/utils'; @@ -79,7 +79,8 @@ export const registerExternalValues = async (options?: RegisterOptions): Promise provider: { useClass: RedisClientFactory }, postInjectionHook: async (deps: DependencyContainer): Promise => { const redisFactory = deps.resolve(REDIS_CLIENT_FACTORY); - for (const redisIndex of [SERVICES.GEOCODING_REDIS, SERVICES.TTL_REDIS]) { + + for (const redisIndex of [SERVICES.GEOCODING_REDIS, SERVICES.TTL_REDIS, REDIS_SUB]) { const redis = redisFactory.createRedisClient(redisIndex); deps.register(redisIndex, { useValue: redis }); cleanupRegistry.register({ @@ -90,31 +91,23 @@ export const registerExternalValues = async (options?: RegisterOptions): Promise id: redisIndex, }); await redis.connect(); - logger.info(`Connected to ${redisIndex.toString()}`); + + let redisName = redisIndex.toString(); + redisName = redisName.substring(redisName.indexOf('(') + 1, redisName.lastIndexOf(')')); + logger.info(`Connected to ${redisName}`); + + if (redisIndex === REDIS_SUB) { + await redisSubscribe(deps); + } } }, }, - { token: HEALTHCHECK, provider: { useFactory: healthCheckFactory } }, { - token: REDIS_SUB, + token: HEALTHCHECK, provider: { - useFactory: instancePerContainerCachingFactory((): RedisClient => { - const subscriber = createClient(); - return subscriber; - }), - }, - postInjectionHook: async (deps: DependencyContainer): Promise => { - const subscriber = deps.resolve(REDIS_SUB); - cleanupRegistry.register({ - func: async () => { - await subscriber.quit(); - return Promise.resolve(); - }, - id: REDIS_SUB, - }); - await subscriber.connect(); - logger.info('Connected to Redis Subscriber'); - await redisSubscribe(deps); + useFactory: (depContainer): HealthCheck => { + return healthCheckFactory(depContainer); + }, }, }, { diff --git a/src/index.ts b/src/index.ts index b11700e..cea38d6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,11 +15,11 @@ void getApp() .then(({ app, container }) => { depContainer = container; - const logger = container.resolve(SERVICES.LOGGER); + const logger = depContainer.resolve(SERVICES.LOGGER); const server = createTerminus(createServer(app), { // eslint-disable-next-line @typescript-eslint/naming-convention - healthChecks: { '/liveness': container.resolve(HEALTHCHECK) }, - onSignal: container.resolve(ON_SIGNAL), + healthChecks: { '/liveness': depContainer.resolve(HEALTHCHECK) }, + onSignal: depContainer.resolve(ON_SIGNAL), }); server.listen(port, () => { @@ -28,12 +28,12 @@ void getApp() }) .catch(async (error: Error) => { const errorLogger = - depContainer?.isRegistered(SERVICES.LOGGER) == true + depContainer?.isRegistered(SERVICES.LOGGER) === true ? depContainer.resolve(SERVICES.LOGGER).error.bind(depContainer.resolve(SERVICES.LOGGER)) : console.error; errorLogger({ msg: '😢 - failed initializing the server', err: error }); - if (depContainer?.isRegistered(ON_SIGNAL) == true) { + if (depContainer?.isRegistered(ON_SIGNAL) === true) { const shutDown: () => Promise = depContainer.resolve(ON_SIGNAL); await shutDown(); } diff --git a/src/redis/subscribe.ts b/src/redis/subscribe.ts index c5bd181..fc72cf6 100644 --- a/src/redis/subscribe.ts +++ b/src/redis/subscribe.ts @@ -29,6 +29,7 @@ export const redisSubscribe = async (deps: DependencyContainer): Promise(SERVICES.LOGGER); const subscriber = deps.resolve(REDIS_SUB); + logger.debug('Redis subscriber init'); const ttlDB = config.get('redis.databases.ttlIndex'); const geocodingDB = config.get('redis.databases.geocodingIndex'); const redisTTL = config.get('redis.ttl');