0

In order to capture the health of each node in multiple clusters I need to invoke them through http calls inside for loop but loop ends before the status comes back from servers failing the program to work correctly.

module.exports = function(robot) {
  robot.respond(/nonprodoauthhealthcheck/i, function(msg){
    var healthcheck=[];
    var nodes = [{
        "cluster": ["https://testurl1.com", "https://testurl2.com"],
        "client_id": "clientid1",
        "client_secret": "password1"
      },
      {
        "cluster": ["https://testur3.com", "https://testurl4"],
        "client_id": "clientid2",
        "client_secret": "password2"
      }
    ];
    for(let i=0;i<nodes.length;i++){
      console.log("i="+i)
      client_id=nodes[i].client_id;
      client_secret= nodes[i].client_secret;
      clusteritem=nodes[i].cluster;
      for(let j=0;j<clusteritem.length;j++){
        var data="client_id="+client_id+"&client_secret="+client_secret+"&grant_type=client_credentials";
        var queryJobUrls=clusteritem[j];
        console.log("j="+j)
        getJobUrls(queryJobUrls,data)
        .then(function(response){
          //msg.reply(response)
          healthcheck.push(
            {
              "url":clusteritem[j],
              "status":response
            }
          )
        })
        .catch(function(error){
          //msg.reply(error)
          healthcheck.push(
            {
              "url":clusteritem[j],
              "status":error
            }
          )
        })
      };
      }
      //for(let k=0;k<healthcheck.length;k++){}
      msg.reply(healthcheck);
    });

  function getJobUrls(queryJobUrls,data) {
    return new Promise(function(resolve, reject){
      var options = {
        rejectUnauthorized: false
      }
       robot.http(queryJobUrls, options).header('Content-Type', 'application/x-www-form-urlencoded').post(data)(function(err, response, body) {
        console.log("inside oauth call")
        if (err != null){
          reject(err);
        }
        else {
          resolve(body);
        }
      });
    })
  }
}

I expect the code to populate a healthcheck array and look something like this:

healthcheck = [{"url":"http://testurl1.com",status="response from http call"},{"url":"http://testurl2.com",status="response from http call"},{"url":"http://testurl3.com",status="response from http call"},{"url":"http://testur4.com",status="response from http call"}]
Luck888
  • 27
  • 4

1 Answers1

0

Before invoking msg.reply with healthcheck parameter you need to make sure that all the promises are resolved and their results are available in healthcheck. Here we use Promise.all to ensure that.

module.exports = function (robot) {
        robot.respond(/nonprodoauthhealthcheck/i, function (msg) {
            var healthcheck = [];
            var nodes = [{
                "cluster": ["https://testurl1.com", "https://testurl2.com"],
                "client_id": "clientid1",
                "client_secret": "password1"
            },
            {
                "cluster": ["https://testur3.com", "https://testurl4"],
                "client_id": "clientid2",
                "client_secret": "password2"
            }
            ];
            const promises = [];
            for (let i = 0; i < nodes.length; i++) {
                console.log("i=" + i)
                client_id = nodes[i].client_id;
                client_secret = nodes[i].client_secret;
                clusteritem = nodes[i].cluster;

                for (let j = 0; j < clusteritem.length; j++) {
                    var data = "client_id=" + client_id + "&client_secret=" + client_secret + "&grant_type=client_credentials";
                    var queryJobUrls = clusteritem[j];
                    console.log("j=" + j)
                    promises.push(getJobUrls(queryJobUrls, data, clusteritem[j]));
                }
            }
            const promise = Promise.all(promises);
            promise.then(res => {
                res.forEach(r => {
                    healthcheck.push({
                        url: r.url,
                        status: r.body
                    })
                });
                msg.reply(healthcheck);
            })
        });

        function getJobUrls(queryJobUrls, data, url) {
            return new Promise(function (resolve, reject) {
                var options = {
                    rejectUnauthorized: false
                }
                robot.http(queryJobUrls, options).header('Content-Type', 'application/x-www-form-urlencoded').post(data)(function (err, response, body) {
                    console.log("inside oauth call")
                    if (err != null) {
                        reject({ err, url });
                    }
                    else {
                        resolve({ body, url });
                    }
                });
            })
        }
    }
Luck888
  • 27
  • 4
Boney
  • 2,072
  • 3
  • 18
  • 23
  • a quick question, promise.all works if all promises resolve. In case some of them throws error I won't be able to capture the health of servers or the error logs. How do I handle this. – Luck888 Apr 15 '19 at 06:00
  • You can do a .catch on the `promise` object for the failure condition as you had initially. – Boney Apr 15 '19 at 06:07
  • Thanks Boney, I will re-accept the answer – Luck888 Apr 16 '19 at 11:03