Skip to content

Commit

Permalink
fix(#1781): Handle promise rejections in CloudSQL samples (#1782)
Browse files Browse the repository at this point in the history
* update cloud sql postgres and mysql samples to handle rejections and exit on unhandled rejections

* handled promise rejection for pool and table creation in mysql sample

* Update server.js

* Update server.js

* refactor pool and schema setup

* Update region tag

Co-authored-by: F. Hinkelmann <[email protected]>
  • Loading branch information
shubha-rajan and fhinkel authored May 7, 2020
1 parent ae28735 commit 479077d
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 54 deletions.
98 changes: 64 additions & 34 deletions cloud-sql/mysql/mysql/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ const logger = winston.createLogger({
});

// [START cloud_sql_mysql_mysql_create]
let pool;
const createPool = async () => {
pool = await mysql.createPool({
return await mysql.createPool({
user: process.env.DB_USER, // e.g. 'my-db-user'
password: process.env.DB_PASS, // e.g. 'my-db-password'
database: process.env.DB_NAME, // e.g. 'my-database'
Expand Down Expand Up @@ -88,7 +87,7 @@ const createPool = async () => {
};
// [END cloud_sql_mysql_mysql_create]

const ensureSchema = async () => {
const ensureSchema = async (pool) => {
// Wait for tables to be created (if they don't already exist).
await pool.query(
`CREATE TABLE IF NOT EXISTS votes
Expand All @@ -98,40 +97,66 @@ const ensureSchema = async () => {
console.log(`Ensured that table 'votes' exists`);
};

let schemaReady;

createPool().then(() => (schemaReady = ensureSchema()));

const awaitSchema = async (req, res, next) => {
await schemaReady;
next();
};
let pool;
const poolPromise = createPool()
.then(async (pool) => {
await ensureSchema(pool);
return pool;
})
.catch((err) => {
logger.error(err);
process.exit(1)
});

app.use(awaitSchema);
app.use(async (req, res, next) => {
if (pool) {
return next();
}
try {
pool = await poolPromise;
next();
}
catch (err) {
logger.error(err);
return next(err);
}
});

// Serve the index page, showing vote tallies.
app.get('/', async (req, res) => {
// Get the 5 most recent votes.
const recentVotesQuery = pool.query(
'SELECT candidate, time_cast FROM votes ORDER BY time_cast DESC LIMIT 5'
);

// Get votes
const stmt = 'SELECT COUNT(vote_id) as count FROM votes WHERE candidate=?';
const tabsQuery = pool.query(stmt, ['TABS']);
const spacesQuery = pool.query(stmt, ['SPACES']);

// Run queries concurrently, and wait for them to complete
// This is faster than await-ing each query object as it is created
const recentVotes = await recentVotesQuery;
const [tabsVotes] = await tabsQuery;
const [spacesVotes] = await spacesQuery;

res.render('index.pug', {
recentVotes,
tabCount: tabsVotes.count,
spaceCount: spacesVotes.count,
});
try {
// Get the 5 most recent votes.
const recentVotesQuery = pool.query(
'SELECT candidate, time_cast FROM votes ORDER BY time_cast DESC LIMIT 5'
);

// Get votes
const stmt = 'SELECT COUNT(vote_id) as count FROM votes WHERE candidate=?';
const tabsQuery = pool.query(stmt, ['TABS']);
const spacesQuery = pool.query(stmt, ['SPACES']);

// Run queries concurrently, and wait for them to complete
// This is faster than await-ing each query object as it is created
const recentVotes = await recentVotesQuery;
const [tabsVotes] = await tabsQuery;
const [spacesVotes] = await spacesQuery;

res.render('index.pug', {
recentVotes,
tabCount: tabsVotes.count,
spaceCount: spacesVotes.count,
});
}
catch(err) {
logger.error(err);
res
.status(500)
.send(
'Unable to load page. Please check the application logs for more details.'
)
.end();
}

});

// Handle incoming vote requests and inserting them into the database.
Expand All @@ -153,7 +178,7 @@ app.post('/', async (req, res) => {
// If something goes wrong, handle the error in this section. This might
// involve retrying or adjusting parameters depending on the situation.
// [START_EXCLUDE]
logger.err(err);
logger.error(err);
res
.status(500)
.send(
Expand All @@ -173,4 +198,9 @@ const server = app.listen(PORT, () => {
console.log('Press Ctrl+C to quit.');
});

process.on('unhandledRejection', err => {
console.error(err);
process.exit(1);
});

module.exports = server;
2 changes: 1 addition & 1 deletion cloud-sql/mysql/mysql/test/server.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ stubMysql.createPool.returns(poolStub);
const server = require('../server.js');

it('check index page', async () => {
const response = await request(server).get('/').timeout(1000);
const response = await request(server).get('/').timeout(3000);

assert.strictEqual(response.status, 200);
});
Expand Down
13 changes: 10 additions & 3 deletions cloud-sql/postgres/knex/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ const getVoteCount = async (knex, candidate) => {
return await knex('votes').count('vote_id').where('candidate', candidate);
};

app.get('/', (req, res) => {
(async function () {
app.get('/', async (req, res) => {
try {
// Query the total count of "TABS" from the database.
const tabsResult = await getVoteCount(knex, 'TABS');
const tabsTotalVotes = parseInt(tabsResult[0].count);
Expand Down Expand Up @@ -183,7 +183,14 @@ app.get('/', (req, res) => {
voteDiff: voteDiff,
leaderMessage: leaderMessage,
});
})();
}
catch(err) {
res
.status(500)
.send('Unable to load page; see logs for more details.')
.end();
}

});

app.post('/', async (req, res) => {
Expand Down
38 changes: 22 additions & 16 deletions cloud-sql/sqlserver/mssql/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const logger = winston.createLogger({
});

// [START cloud_sql_server_mssql_create]
let pool;
const createPool = async () => {
let config = {pool: {}};
config.user = process.env.DB_USER; // e.g. 'my-db-user'
Expand Down Expand Up @@ -82,11 +81,11 @@ const createPool = async () => {
// [END cloud_sql_server_mssql_backoff]

// [END_EXCLUDE]
pool = await mssql.connect(config);
return await mssql.connect(config);
};
// [END cloud_sql_mysql_mysql_create]
// [END cloud_sql_server_mssql_create]

const ensureSchema = async () => {
const ensureSchema = async (pool) => {
// Wait for tables to be created (if they don't already exist).
await pool.request()
.query(
Expand All @@ -101,21 +100,28 @@ const ensureSchema = async () => {
console.log(`Ensured that table 'votes' exists`);
};

let schemaReady;
let pool;
const poolPromise = createPool()
.then(async (pool) => {
await ensureSchema(pool);
return pool;
})
.catch((err) => {
logger.error(err);
process.exit(1);
});

app.use(async (req, res, next) => {
if (schemaReady) {
if (pool) {
return next();
}
try {
pool = await poolPromise;
next();
}
else {
try {
await createPool();
schemaReady = await ensureSchema();
next();
}
catch (err) {
logger.error(err);
return next(err);
}
catch (err) {
logger.error(err);
return next(err);
}
});

Expand Down

0 comments on commit 479077d

Please sign in to comment.