Check DB connection in health-check
MODIFY
src/server/ExpressUtils.ts
src/server/ExpressUtils.ts
import express, { Application, NextFunction, Request, Response } from 'express';
-import Configuration from '../utils/Configuration';
import Constants from '../utils/Constants';
import Logging from '../utils/Logging';
import { StatusCodes } from 'http-status-codes';
@@ -61,7 +60,12 @@ export default class ExpressUtils {
expressApplication.use(Logging.traceExpressError.bind(this));
}
- private static healthCheckService(req: Request, res: Response, next: NextFunction): void {
+ private static async healthCheckService(req: Request, res: Response, next: NextFunction): Promise<void> {
+ const pingSuccess = await global.database.ping();
+ if (pingSuccess) {
res.sendStatus(StatusCodes.OK);
+ } else {
+ res.sendStatus(StatusCodes.INTERNAL_SERVER_ERROR);
+ }
}
}

MODIFY
src/server/ServerUtils.ts
src/server/ServerUtils.ts
import { ServerAction, ServerProtocol, ServerType } from '../types/Server';
-import http, { IncomingMessage, ServerResponse } from 'http';
import { AddressInfo } from 'net';
import CentralSystemServerConfiguration from '../types/configuration/CentralSystemServerConfiguration';
import Constants from '../utils/Constants';
import Logging from '../utils/Logging';
-import { StatusCodes } from 'http-status-codes';
+import http from 'http';
import https from 'https';
export class ServerUtils {
@@ -22,8 +21,7 @@ export class ServerUtils {
Logging.logConsoleDebug(logMsg);
}
- public static createHttpServer(serverConfig: CentralSystemServerConfiguration,
- requestListener: http.RequestListener = ServerUtils.defaultHttpServerRequestListener.bind(this)): http.Server {
+ public static createHttpServer(serverConfig: CentralSystemServerConfiguration, requestListener: http.RequestListener): http.Server {
let httpServer: http.Server;
// Create the HTTP server
if (serverConfig.protocol === ServerProtocol.HTTPS || serverConfig.protocol === ServerProtocol.WSS) {
@@ -66,14 +64,4 @@ export class ServerUtils {
private static getHttpServerAddress(httpServer: http.Server): string {
return (httpServer.address() as AddressInfo).address;
}
-
- private static defaultHttpServerRequestListener(req: IncomingMessage, res: ServerResponse): void {
- if (req.url === Constants.HEALTH_CHECK_ROUTE) {
- res.writeHead(StatusCodes.OK);
- res.end();
- } else {
- res.writeHead(StatusCodes.BAD_REQUEST);
- res.end('Unsupported request\n');
- }
- }
}

MODIFY
src/server/ocpp/json/JsonCentralSystemServer.ts
src/server/ocpp/json/JsonCentralSystemServer.ts
@@ -94,8 +94,23 @@ export default class JsonCentralSystemServer extends CentralSystemServer {
await wsConnection.onPong(ocppMessage);
}
}
- }).any('/health-check', (res: HttpResponse) => {
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
+ }).any(Constants.HEALTH_CHECK_ROUTE, async (res: HttpResponse) => {
+ res.onAborted(() => {
+ res.aborted = true;
+ });
+ const pingSuccess = await global.database.ping();
+ if (!res.aborted) {
+ if (pingSuccess) {
res.end('OK');
+ } else {
+ res.writeStatus('500');
+ res.end('KO');
+ }
+ }
+ }).any('/*', (res: HttpResponse) => {
+ res.writeStatus('404');
+ res.end();
}).listen(this.centralSystemConfig.port, (token) => {
if (token) {
Logging.logConsoleDebug(`${ServerType.JSON_SERVER} Server listening on 'http://${this.centralSystemConfig.host}:${this.centralSystemConfig.port}'`);

MODIFY
src/storage/mongodb/MongoDBStorage.ts
src/storage/mongodb/MongoDBStorage.ts
@@ -72,8 +72,7 @@ export default class MongoDBStorage {
await Logging.logDebug({
tenantID: tenant.id,
action: ServerAction.MONGO_DB,
- message,
- module: MODULE_NAME, method: 'watchDatabaseCollection'
+ message, module: MODULE_NAME, method: 'watchDatabaseCollection'
});
// Trigger callbacks
changeStream.on('change', (changeStreamDocument: ChangeStreamDocument) => {
@@ -283,6 +282,26 @@ export default class MongoDBStorage {
Logging.logConsoleDebug(`Connected to '${this.dbConfig.implementation}' successfully`);
}
+ public async ping(): Promise<boolean> {
+ if (this.database) {
+ try {
+ const result = await this.database.command({ ping: 1 });
+ return (result.ok === 1);
+ } catch (error) {
+ const message = 'Error while pinging the Database!';
+ Logging.logConsoleError(message);
+ await Logging.logError({
+ tenantID: Constants.DEFAULT_TENANT,
+ action: ServerAction.MONGO_DB,
+ module: MODULE_NAME, method: 'ping',
+ message, detailedMessages: { error: error.stack }
+ });
+ return false;
+ }
+ }
+ return true;
+ }
+
private async checkDatabase(): Promise<void> {
// Safety check
if (!this.database) {
@@ -342,13 +361,12 @@ export default class MongoDBStorage {
}
} catch (error) {
const message = 'Error while checking Database in tenant \'default\'';
- Utils.isDevelopmentEnv() && Logging.logConsoleError(message);
+ Logging.logConsoleError(message);
await Logging.logError({
tenantID: Constants.DEFAULT_TENANT,
action: ServerAction.MONGO_DB,
module: MODULE_NAME, method: 'handleIndexesInCollection',
- message,
- detailedMessages: { error: error.stack }
+ message, detailedMessages: { error: error.stack }
});
}
}
@@ -373,13 +391,12 @@ export default class MongoDBStorage {
}
} catch (error) {
const message = `Error while checking Database in tenant '${tenantId}'`;
- Utils.isDevelopmentEnv() && Logging.logConsoleError(message);
+ Logging.logConsoleError(message);
await Logging.logError({
tenantID: Constants.DEFAULT_TENANT,
action: ServerAction.MONGO_DB,
module: MODULE_NAME, method: 'handleIndexesInCollection',
- message,
- detailedMessages: { error: error.stack }
+ message, detailedMessages: { error: error.stack }
});
}
}
@@ -407,13 +424,12 @@ export default class MongoDBStorage {
await this.database.createCollection(tenantCollectionName);
} catch (error) {
const message = `Error in creating collection '${tenantID}.${tenantCollectionName}': ${error.message as string}`;
- Utils.isDevelopmentEnv() && Logging.logConsoleError(message);
+ Logging.logConsoleError(message);
await Logging.logError({
tenantID: Constants.DEFAULT_TENANT,
action: ServerAction.MONGO_DB,
module: MODULE_NAME, method: 'handleIndexesInCollection',
- message,
- detailedMessages: { error: error.stack, tenantCollectionName, name, indexes }
+ message, detailedMessages: { error: error.stack, tenantCollectionName, name, indexes }
});
}
}
@@ -446,21 +462,19 @@ export default class MongoDBStorage {
tenantID: Constants.DEFAULT_TENANT,
action: ServerAction.MONGO_DB,
module: MODULE_NAME, method: 'handleIndexesInCollection',
- message,
- detailedMessages: { tenantCollectionName, indexes, indexName: databaseIndex.name }
+ message, detailedMessages: { tenantCollectionName, indexes, indexName: databaseIndex.name }
});
}
try {
await this.database.collection(tenantCollectionName).dropIndex(databaseIndex.key);
} catch (error) {
const message = `Error in dropping index '${databaseIndex.name}' in '${tenantCollectionName}': ${error.message}`;
- Utils.isDevelopmentEnv() && Logging.logConsoleError(message);
+ Logging.logConsoleError(message);
await Logging.logError({
tenantID: Constants.DEFAULT_TENANT,
action: ServerAction.MONGO_DB,
module: MODULE_NAME, method: 'handleIndexesInCollection',
- message,
- detailedMessages: { error: error.stack, tenantCollectionName, name, indexes, indexName: databaseIndex.name }
+ message, detailedMessages: { error: error.stack, tenantCollectionName, name, indexes, indexName: databaseIndex.name }
});
}
}
@@ -479,21 +493,19 @@ export default class MongoDBStorage {
tenantID: Constants.DEFAULT_TENANT,
action: ServerAction.MONGO_DB,
module: MODULE_NAME, method: 'handleIndexesInCollection',
- message,
- detailedMessages: { tenantCollectionName, name, indexes, indexFields: index.fields, indexOptions: index.options }
+ message, detailedMessages: { tenantCollectionName, name, indexes, indexFields: index.fields, indexOptions: index.options }
});
}
try {
await this.database.collection(tenantCollectionName).createIndex(index.fields, index.options);
} catch (error) {
const message = `Error in creating index '${JSON.stringify(index.fields)}' with options '${JSON.stringify(index.options)}' in '${tenantCollectionName}': ${error.message as string}`;
- Utils.isDevelopmentEnv() && Logging.logConsoleError(message);
+ Logging.logConsoleError(message);
await Logging.logError({
tenantID: Constants.DEFAULT_TENANT,
action: ServerAction.MONGO_DB,
module: MODULE_NAME, method: 'handleIndexesInCollection',
- message,
- detailedMessages: { error: error.stack, tenantCollectionName, name, indexes, indexFields: index.fields, indexOptions: index.options }
+ message, detailedMessages: { error: error.stack, tenantCollectionName, name, indexes, indexFields: index.fields, indexOptions: index.options }
});
}
}
@@ -501,13 +513,12 @@ export default class MongoDBStorage {
}
} catch (error) {
const message = `Unexpected error in handling Collection '${tenantID}.${name}': ${error.message as string}`;
- Utils.isDevelopmentEnv() && Logging.logConsoleError(message);
+ Logging.logConsoleError(message);
await Logging.logError({
tenantID: Constants.DEFAULT_TENANT,
action: ServerAction.MONGO_DB,
module: MODULE_NAME, method: 'handleIndexesInCollection',
- message,
- detailedMessages: { error: error.stack, tenantID, name, indexes }
+ message, detailedMessages: { error: error.stack, tenantID, name, indexes }
});
}
}

MODIFY
src/utils/Logging.ts
src/utils/Logging.ts
@@ -2,9 +2,8 @@ import { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
import { Log, LogLevel } from '../types/Log';
import { NextFunction, Request, Response } from 'express';
import PerformanceRecord, { PerformanceRecordGroup, PerformanceTracingData } from '../types/Performance';
-import { ServerAction, ServerType } from '../types/Server';
-import global, { ActionsResponse } from '../types/GlobalType';
+import { ActionsResponse } from '../types/GlobalType';
import AppAuthError from '../exception/AppAuthError';
import AppError from '../exception/AppError';
import BackendError from '../exception/BackendError';
@@ -17,6 +16,7 @@ import { OCPIResult } from '../types/ocpi/OCPIResult';
import { OCPPStatus } from '../types/ocpp/OCPPClient';
import { OICPResult } from '../types/oicp/OICPResult';
import PerformanceStorage from '../storage/mongodb/PerformanceStorage';
+import { ServerAction } from '../types/Server';
import Tenant from '../types/Tenant';
import User from '../types/User';
import UserToken from '../types/UserToken';

Check DB connection in health-check