[client-sync] Shim sequelize to timeout after 1 minute

Summary:
Sequelize can sometimes return promises that will never resolve or
reject. We can wrap the promises we get back from sequelize in a
bluebird promise which gives us the ability to timeout these abandoned
promises. This way, we can track down issues in sequelize as well as
unblocking stuck sync loops.

Test Plan: Run locally, verify that timeouts occur

Reviewers: juan, evan, spang

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D4192
This commit is contained in:
Mark Hahnenberg 2017-03-10 12:06:23 -08:00
parent 25ba62e02a
commit c971ed03e2
2 changed files with 40 additions and 0 deletions

View file

@ -1,8 +1,11 @@
/* eslint global-require: 0 */
import Sequelize from 'sequelize'; // eslint-disable-line
import {ComponentRegistry} from 'nylas-exports'
import {createLogger} from './src/shared/logger'
import shimSequelize from './src/shared/shim-sequelize'
export function activate() {
shimSequelize(Sequelize);
global.Logger = createLogger()
require('./src/local-api');
require('./src/local-sync-worker');

View file

@ -0,0 +1,37 @@
const _ = require('underscore');
const DEFAULT_SEQUELIZE_SHIM_TIMEOUT = 60 * 1000; // 1 min
const shimObject = (obj) => {
Object.keys(obj).forEach(key => {
// Skip internal methods.
if (key.startsWith('_')) {
return;
}
const prop = obj[key];
// Only patch methods.
if (!_.isFunction(prop)) {
return;
}
obj[key] = function(...args) { // eslint-disable-line
const result = prop.call(this, ...args);
if (result && _.isFunction(result.then)) {
return new Promise(async (resolve, reject) => {
try {
resolve(await result);
} catch (err) {
reject(err);
}
}).timeout(DEFAULT_SEQUELIZE_SHIM_TIMEOUT, `${key} timed out`);
}
return result;
};
});
};
export default function shimSequelize(Sequelize) {
shimObject(Sequelize.Model);
shimObject(Sequelize.Instance.prototype);
}