From dcc7a81367665bfb4e875fb217a87a5f8e000d4b Mon Sep 17 00:00:00 2001 From: Clemens Wolff Date: Tue, 15 Aug 2017 12:01:49 -0700 Subject: [PATCH 1/3] Block server start until Cassandra is initialized The first request to Cassandra is very slow (on the order of 20 seconds during my testing), I reckon because the connection and pool are being built up. Subsequent requests are much faster (sub-second). We don't want our users to have a problem with hitting the slow first request, so we should warm up the Cassandra connection before we let the server start. In this way, when we re-deploy the GraphQL server, we'll simply continue running the instances of the old code in the load balancer until the new server is fully operational and has warmed up the Cassandra connection. --- server.js | 14 ++++++++++---- src/clients/cassandra/CassandraConnector.js | 10 ++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index 0f81529..07fb413 100644 --- a/server.js +++ b/server.js @@ -35,8 +35,6 @@ app.use(function(req, res, next) { } }); -console.log('PORT: ' + port); - app.use(bodyParser.json({limit: '50mb'})); app.use(bodyParser.urlencoded({limit: '50mb', extended: true})); @@ -64,6 +62,14 @@ app.use('/api/settings', graphqlHTTP({ graphiql: true })); -const server = http.createServer(app); +function startServer() { + console.log(`PORT: ${port}`); + const server = http.createServer(app); + server.listen(port, function () {}); +} + +const serverStartBlocker = process.env.ENABLE_V2 + ? require('./src/clients/cassandra/CassandraConnector').initialize() + : Promise.resolve(); -server.listen(port, function () {}); \ No newline at end of file +serverStartBlocker.then(startServer); \ No newline at end of file diff --git a/src/clients/cassandra/CassandraConnector.js b/src/clients/cassandra/CassandraConnector.js index bc530df..2099893 100644 --- a/src/clients/cassandra/CassandraConnector.js +++ b/src/clients/cassandra/CassandraConnector.js @@ -108,7 +108,17 @@ function executeQueries(queries) { }); } +/** + * Should be called on server start to warm up the connection to + * Cassandra so that subsequent calls are fast. + * @returns {Promise} + */ +function intialize() { + return executeQuery('select sitename from fortis.sitesettings limit 1', []); +} + module.exports = { + initialize: trackDependency(intialize, 'Cassandra', 'initialize'), executeBatchMutations: trackDependency(executeBatchMutations, 'Cassandra', 'executeBatchMutations'), executeQueries: trackDependency(executeQueries, 'Cassandra', 'executeQueries'), executeQuery: trackDependency(executeQuery, 'Cassandra', 'executeQuery') From e11d05f32dc2b50e859b12e20c8734de67d3128e Mon Sep 17 00:00:00 2001 From: Clemens Wolff Date: Tue, 15 Aug 2017 12:05:33 -0700 Subject: [PATCH 2/3] Avoid relying on built-in Promise --- server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.js b/server.js index 07fb413..8529766 100644 --- a/server.js +++ b/server.js @@ -70,6 +70,6 @@ function startServer() { const serverStartBlocker = process.env.ENABLE_V2 ? require('./src/clients/cassandra/CassandraConnector').initialize() - : Promise.resolve(); + : require('promise').resolve(); serverStartBlocker.then(startServer); \ No newline at end of file From c595ac0e3a0d1c0b8b962ae0389a544b5653bd05 Mon Sep 17 00:00:00 2001 From: Clemens Wolff Date: Tue, 15 Aug 2017 12:06:55 -0700 Subject: [PATCH 3/3] Add error handling --- server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.js b/server.js index 8529766..c2dd49f 100644 --- a/server.js +++ b/server.js @@ -72,4 +72,4 @@ const serverStartBlocker = process.env.ENABLE_V2 ? require('./src/clients/cassandra/CassandraConnector').initialize() : require('promise').resolve(); -serverStartBlocker.then(startServer); \ No newline at end of file +serverStartBlocker.then(startServer).catch(console.error); \ No newline at end of file