Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 44 additions & 26 deletions src/common/utils.ts
Original file line number Diff line number Diff line change
@@ -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<void> = (container: DependencyContainer): void => {
const logger = container.resolve<Logger>(SERVICES.LOGGER);
const geocodingRedis = container.resolve<RedisClient>(SERVICES.GEOCODING_REDIS);
const ttlRedis = container.resolve<RedisClient>(SERVICES.TTL_REDIS);
export const healthCheckFactory = (container: DependencyContainer): HealthCheck => {
return async (): Promise<void> => {
const logger = container.resolve<Logger>(SERVICES.LOGGER);
const geocodingRedis = container.resolve<RedisClient>(SERVICES.GEOCODING_REDIS);
const ttlRedis = container.resolve<RedisClient>(SERVICES.TTL_REDIS);

geocodingRedis
.ping()
.then(() => {
return;
})
.catch((error: Error) => {
logger.error({
message: `Healthcheck failed for GeocodingRedis.`,
error,
});
});
const promises: Promise<unknown>[] = [];

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();
};
};
39 changes: 16 additions & 23 deletions src/containerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -79,7 +79,8 @@ export const registerExternalValues = async (options?: RegisterOptions): Promise
provider: { useClass: RedisClientFactory },
postInjectionHook: async (deps: DependencyContainer): Promise<void> => {
const redisFactory = deps.resolve<RedisClientFactory>(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({
Expand All @@ -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<void> => {
const subscriber = deps.resolve<RedisClient>(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);
},
},
},
{
Expand Down
10 changes: 5 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ void getApp()
.then(({ app, container }) => {
depContainer = container;

const logger = container.resolve<Logger>(SERVICES.LOGGER);
const logger = depContainer.resolve<Logger>(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, () => {
Expand All @@ -28,12 +28,12 @@ void getApp()
})
.catch(async (error: Error) => {
const errorLogger =
depContainer?.isRegistered(SERVICES.LOGGER) == true
depContainer?.isRegistered(SERVICES.LOGGER) === true
? depContainer.resolve<Logger>(SERVICES.LOGGER).error.bind(depContainer.resolve<Logger>(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<void> = depContainer.resolve(ON_SIGNAL);
await shutDown();
}
Expand Down
1 change: 1 addition & 0 deletions src/redis/subscribe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const redisSubscribe = async (deps: DependencyContainer): Promise<RedisCl
const logger = deps.resolve<Logger>(SERVICES.LOGGER);
const subscriber = deps.resolve<RedisClient>(REDIS_SUB);

logger.debug('Redis subscriber init');
const ttlDB = config.get<number>('redis.databases.ttlIndex');
const geocodingDB = config.get<number>('redis.databases.geocodingIndex');
const redisTTL = config.get<number>('redis.ttl');
Expand Down