New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add status.js and its tests #238
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AnkshitJain please see the suggested changes
util/environmentCheck.js
Outdated
}; | ||
|
||
module.exports = { | ||
check, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comma at the end is not required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good.
load_balancer/load_balancer.js
Outdated
@@ -13,13 +13,15 @@ var http = require('http'); | |||
var bodyParser = require('body-parser'); | |||
var fs = require('fs'); | |||
var sys = require('sys'); | |||
var exec = require('child_process').exec; | |||
var { exec } = require('child_process'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please fix the new codeclimate issues. The apriori issues can be left alone.
@@ -17,7 +18,8 @@ | |||
], | |||
"author": "Rajat Agarwal", | |||
"contributors": [ | |||
"Tejas Sangol", "Gaurav Narula" | |||
"Tejas Sangol", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add your name here
load_balancer/status.js
Outdated
resolve(undefined); | ||
} | ||
|
||
const resultJson = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per line-34 of logger.js, we are to use three properties in a json file for node identity. The properties are: role, hostname and port. If we use the same three properties here as well, we would be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another advantage of receiving the role of a node is that the status.js module becomes independent of its ties to execution nodes.
load_balancer/status.js
Outdated
const logger = new Logger(loggerConfig); | ||
|
||
function getComponentStatus(node) { | ||
return new Promise((resolve) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The closure object is too long and has too many initializations. Is it possible to split this object into two smaller objects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A coding rule known as step down rule from Robert Martin's Clean Code book will certainly help get a good structure. In step down rule, if f2() calls f1(), then code for f2() comes first in the file followed by f1().
f3551ad
to
511867c
Compare
@prasadtalasila Please have a look at the updated commit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AnkshitJain please see the suggested changes.
@@ -1,22 +1,27 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the sake of uniformity, it is better to change all the configuration files to have complete node identities. There is going to be some redundancy in configuration which can be taken care of later during code refactoring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you suggest making changes to all the execution node configuration files i.e. conf.json and scores.json?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also to the configuration files of main_server as well.
|
||
var job_queue = []; | ||
if(process.env.mode !== "TESTING") | ||
{ | ||
server.listen(nodes_data.host_port.port); | ||
console.log("Listening at "+nodes_data.host_port.port); | ||
server.listen(nodes_data.load_balancer.port); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please fix the code quality issues raised here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check doesn't show any new errors here. Can you tell what the error is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may need to install the codeclimate plugin on chrome / chromium browser to have the codeclimate issues show up on the PR page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expect 4 errors here:
- Opening curly brace does not appear on the same line as controlling statement.
- Strings must use single quote.
- Unexpected string concatenation.
- Infix operators must be spaced.
These are previously existing quality errors, and I haven't tried to fix them. The only reason this line has a change is because the host name property was added there and the object in the configuration file nodes_data_config.json had the property name changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more issues exist. I am not able to copy paste the consolidated list.
load_balancer/load_balancer.js
Outdated
lbStatus.status = 'up'; | ||
status.checkStatus((result) => { | ||
//since the request is being processed, it is assumed that load balancer is up | ||
const statusJson = result; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fine, but there is a better library named lodash that is good at manipulating json objects. You might want to use it.
@@ -0,0 +1,102 @@ | |||
/* eslint import/no-dynamic-require: 0 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like this module can make use of lodash module to simplify the logic. Please see if you can use it to reduce the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be its just me, but the code of status.js module does not look readable to me. Is there a way to simplify the code of status.js?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed the lodash vs es6 debate. Its definitely worth using lodash in the project. I would rather introduce lodash more strategically by identifying the features of lodash that help us, note them down for use during refactoring. Nothing much to do now.
@prasadtalasila Please have a look at the updated commit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AnkshitJain please check the code review comments.
"hostname": "localhost", | ||
"port": "8086" | ||
} | ||
], | ||
"server_info": { | ||
"role": "main_server", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The database component would have role property too. Its value is to be set to database.
@@ -150,6 +150,7 @@ | |||
- "../log/load_balancer:/log" | |||
env: | |||
LOGGERCONFIG: "/etc/util/logger.json" | |||
LBCONFIG: "/etc/load_balancer/nodes_data_conf.json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be better to set the configuration environment variables for all the components.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LOGGERCONFIG
variable would be used by all the components and is included as an environment variable for main_server, load_balancer and execution_nodes containers. The same cannot be said for the LBCONFIG
variable. It has the node details and that is not required by the other containers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not ask for adding LBCONFIG environment variable to other containers. I suggested adding mainserver configuration variable to mainserver, execution node configuration variable to execution node. Done that way, there would not be any code replacements in the tests.
load_balancer/status.js
Outdated
|
||
const logger = new Logger(loggerConfig); | ||
|
||
const getComponentResponse = function getComponentResponse(node, resolve) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that the resolve() callback has been put in place for testability. Does the callback serve any other purpose?
load_balancer/status.js
Outdated
this.nodes = nodes; | ||
this.promises = []; | ||
for (let i = 0; i < this.nodes.length; i += 1) { | ||
this.promises.push(getComponentStatus(this.nodes[i])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting the invocation of getComponentStatus() only in the constructor will result in staus update at the time of object creation. This is not the desirable behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At best, the code can resolve status of each component only once.
|
||
var job_queue = []; | ||
if(process.env.mode !== "TESTING") | ||
{ | ||
server.listen(nodes_data.host_port.port); | ||
console.log("Listening at "+nodes_data.host_port.port); | ||
server.listen(nodes_data.load_balancer.port); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more issues exist. I am not able to copy paste the consolidated list.
@@ -0,0 +1,102 @@ | |||
/* eslint import/no-dynamic-require: 0 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed the lodash vs es6 debate. Its definitely worth using lodash in the project. I would rather introduce lodash more strategically by identifying the features of lodash that help us, note them down for use during refactoring. Nothing much to do now.
load_balancer/status.js
Outdated
resolve('down'); | ||
} else if (body.toString() === 'true') { | ||
logger.debug(`Node at ${node.hostname}:${node.port} is up and running.`); | ||
resolve('up'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the name of the callback function consistent with the nomeclature of promises?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the promises callback are resolve and reject.
@prasadtalasila The suggested structure of having the |
@AnkshitJain Then lets follow the established conventions of ES6. Let's ignore the step down rule for now. |
@AnkshitJain async/await looks good. Please use the same. |
9c693d4
to
d1a3c47
Compare
@prasadtalasila Please have a look at the updated commit. Code climate gives an error related to the code complexity. Initially when the method getComponentStatus was in two separate parts, it gave 2 errors saying the code was similar. Can you suggest what can be done in this case? |
@AnkshitJain Please modify the README.md file by updating the codeclimate badge to the following code.
Right next to codeclimate code quality badge, you can put the code coverage badge.
Right now, this badge shows a question mark until we put in a code coverage tool. That's okay. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AnkshitJain I am yet to complete the code review. In the mean while, please go through the following comments.
load_balancer/status.js
Outdated
|
||
const logger = new Logger(loggerConfig); | ||
|
||
async function getComponentStatus(node) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about the following code structure? (BTW, there is a compilation error in the code snippet, please only use the idea, not the actual code)
function isValidNode(node) {
hostname = node.hostname;
port = node.port;
role = node.role;
if (hostname === undefined || port === undefined || role == undefined)
return false;
else
return true;
}
async function getComponentStatus(node) {
if (!isValidNode(node))
throw new InvalidNodeException();
const resultJson = Object.assign({}, node);
try {
const body = await request.get(`https://${node.hostname}:${node.port}/connectionCheck`);
if (body.toString() === 'true') {
logger.debug(`Node at ${node.hostname}:${node.port} is up and running.`);
resultJson.status = 'up';
}
} catch (err) {
logger.error(`Error connecting to ${node.hostname}:${node.port}`);
logger.error(err);
resultJson.status = 'down';
}
You also need to define InvalidNodeException class. I see the value in putting both isValidNode() and InvalidNodeException in a module inside util/. That way, other components can cross check their configuration values as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What properties wil the error class would require apart from an error message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just the error status message is sufficient.
load_balancer/status.js
Outdated
return resultJson; | ||
} | ||
|
||
async function getPromises(nodes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous name of this function sounds better. getPromises() name is too generic and unintuitive.
Path in docker containers: "/etc/main_server/APIKeys.json" | ||
*/ | ||
|
||
check('MSCONFIG'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check function is checking the definition of the environment variable. It can also check for the existence of the file and the read permissions. Once the existence and permissions checks pass, we can subject the configuration file to validity check by iterating the isNodeValid() function over all the entries in the configuration file.
This is just an idea. Please suggest alternatives and improvements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AnkshitJain
The scope of the above suggestion is very big. I have opened a new issue #250 to keep track of the suggestion. Let's wrap up this PR with the existing check() functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AnkshitJain a few more suggestions.
@@ -0,0 +1,9 @@ | |||
const check = function check(variable) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests are missing for this function. You can also think of putting in the isValidNode() and InValidNodeException in this module itself.
@AnkshitJain I am done with my review. I don't have any further suggestions to make. Everything else looks good for now. |
da437bc
to
f819b4f
Compare
@prasadtalasila I have modified the method name |
@AnkshitJain the latest commit looks good. |
@AnkshitJain please provide a tentative timeline to finish up with the pending work on this branch. |
@prasadtalasila Only the tests of environmentCheck.js are remaining, which I plan to add along with the custom error class. The tests will require adding some additional util functions. If the current PR is acceptable, it can be merged and closed, otherwise I will add the custom error class after 14th and it can be left open till then. |
@AnkshitJain any progress on this work? Because of a few commits on dev branch from my side, there are merge conflicts. You have to rebase your branch. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AnkshitJain please make the changes.
load_balancer/load_balancer.js
Outdated
} | ||
|
||
|
||
|
||
setInterval(function () { | ||
connection.query('SELECT 1' ,function(err, rows, fields) { | ||
console.log("keep alive query"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment the console log line.
load_balancer/load_balancer.js
Outdated
setInterval(function () { | ||
connection.query('SELECT 1' ,function(err, rows, fields) { | ||
console.log("keep alive query"); | ||
}); | ||
}, 10000); | ||
}, 100000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeout value here would be half of the socket timeout set in MySQL config file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default value for timeout is 8 hrs. We can have out own custom timeout value with the wait_timeout
variable. It was verified and here is the same.
mysql> SHOW global VARIABLES like "wait_timeout";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
1 row in set (0.07 sec)
We can set the timeout value to 14400 seconds here.
tests/test.sh
Outdated
# change the config file paths in all the relevant js files | ||
sed -i 's/\/etc\/load_balancer/\.\.\/deploy\/configs\/load_balancer/' load_balancer/load_balancer.js | ||
sed -i 's/\/etc\/main_server/\.\.\/deploy\/configs\/main_server/' main_server/main_server.js | ||
#sed -i 's/\/etc\/load_balancer/\.\.\/deploy\/configs\/load_balancer/' load_balancer/load_balancer.js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please remove the next two commented lines. There are equivalent environment config variables.
@prasadtalasila The commit has been updated. Please have a look at it. |
@prasadtalasila Please review the commit and suggest the necessary changes. I have included a
environmentCheck.js
file in/util
directory that checks whether an environment variable is defined or not.This module can be used in other js modules as well.