0

I am trying to write a health check for my code (This check involved communication with Cassandra DB and Kafka).

This is the code I wrote:

// health-check
app.get('/stats/health', function(req, res, next) {
  Promise.all([cassandraPromise, kafkaPromise])
      .then(console.log("Everything is OK"),
      console.log("FAILED!"));
});


var cassandraPromise = new Promise(function(resolve, reject){
  *****.client.state.cassandraClient.execute('SELECT vehicle_id FROM vehicles.vehicles LIMIT 1', function(err) {
    if (err) {
      console.log ('Health Check for Cassandra failed');
      //res.write("Cassandra health check FAILED\n");
      reject(err);
    } else {
      console.log('Health Check for Cassandra passed\n');
      resolve(200);
    }
  });
});

var kafkaPromise = new Promise(function(resolve,reject) {
  stats.kafkaService.producer.send( [{topic: 'health_check', messages: 'health check message'}], function(err,data) {
    if (err) {
      //res.write("Health Check for Kafka failed\n");
      console.log("Health Check for Kafka failed");
      reject(err);
    } else {
      console.log("Health Check for Kafka passed");
      resolve(200);
    }
  });
});

And the error message is:

'queryFetchSize' was not defined. Using default: '25000'

'socketReadTimeout' was not defined. Using default: '30000'

Error in Kafka producer: {"message":"Could not find a broker"}

I have another version to this code (without promises) and it runs properly, so I'm sure that my problem is not with Kafka.

Can you tell me what are the mistakes in my code?

P.S. I also checked out this link: Wrapping Node.js callbacks in Promises using Bluebird and it didn't help me.

EDIT: Here is the working code:

// health-check
app.get('/stats/health', cassandraHealthCheck, kafkaHealthCheck);

function cassandraHealthCheck(req, res, next) {
  ******.client.state.cassandraClient.execute('SELECT vehicle_id FROM vehicles.vehicles LIMIT 1', function(err) {
    if (err) {
      console.log ('Health Check for Cassandra failed');
    } else {
      console.log('Health Check for Cassandra passed');
      next();
    }
  });
}

function kafkaHealthCheck(req, res, next) {
    stats.kafkaService.producer.send( [{topic: 'health_check', messages: 'health check message'}], function(err,data) {
      if (err) {
        console.log("Health Check for Kafka failed");
      } else {
        console.log("Health Check for Kafka passed");
      }
    });
};
Community
  • 1
  • 1
CrazySynthax
  • 13,662
  • 34
  • 99
  • 183

1 Answers1

1

When you do this:

app.get('/stats/health', function(req, res, next) {
  Promise.all([cassandraPromise, kafkaPromise])
});

var cassandraPromise = new Promise(...);
var kafkaPromise = new Promise(...);

you create two promises that will load immediately. I think your kafka client is not ready yet and fails the promise.

Then (let say 30 seconds later), when you call /stats/health, you use the two existing promises, which are already resolved. The Promise.all ends with a failed promise (because kafkaPromise failed 30 seconds ago).

What you want to do is to create a new promise each time:

function checkCassandra() {
  return new Promise(...);
}

function checkKafka() {
  return new Promise(...);
}

app.get('/stats/health', function(req, res, next) {
  Promise.all([checkCassandra(), checkKafka()])
});

That way, you will trigger a call to cassandra/kafka each time you call the health check.

(I asked for the working code to confirm, I'll update my answer if I missed).

David Duponchel
  • 3,959
  • 3
  • 28
  • 36