Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMPROVE] Stop sort callbacks on run #11330

Merged
merged 2 commits into from
Jul 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 53 additions & 54 deletions packages/rocketchat-lib/lib/callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,34 @@ RocketChat.callbacks.priority = {
LOW: 1000
};

const getHooks = hookName => RocketChat.callbacks[hookName] || [];

/*
* Add a callback function to a hook
* @param {String} hook - The name of the hook
* @param {Function} callback - The callback function
*/

RocketChat.callbacks.add = function(hook, callback, priority, id) {
if (priority == null) {
priority = RocketChat.callbacks.priority.MEDIUM;
}
RocketChat.callbacks.add = function(hook, callback, priority, id = Random.id()) {
if (!_.isNumber(priority)) {
priority = RocketChat.callbacks.priority.MEDIUM;
}
callback.priority = priority;
callback.id = id || Random.id();
RocketChat.callbacks[hook] = RocketChat.callbacks[hook] || [];
callback.id = id;
RocketChat.callbacks[hook] = getHooks(hook);

if (RocketChat.callbacks.showTime === true) {
const err = new Error;
callback.stack = err.stack;
}

if (RocketChat.callbacks[hook].find((cb) => cb.id === callback.id)) {
return;
}
RocketChat.callbacks[hook].push(callback);
RocketChat.callbacks[hook] = _.sortBy(RocketChat.callbacks[hook], function(callback) {
return callback.priority || RocketChat.callbacks.priority.MEDIUM;
});
};


Expand All @@ -60,8 +63,8 @@ RocketChat.callbacks.add = function(hook, callback, priority, id) {
* @param {string} id - The callback's id
*/

RocketChat.callbacks.remove = function(hookName, id) {
RocketChat.callbacks[hookName] = _.reject(RocketChat.callbacks[hookName], (callback) => callback.id === id);
RocketChat.callbacks.remove = function(hook, id) {
RocketChat.callbacks[hook] = getHooks(hook).filter(callback => callback.id !== id);
};


Expand All @@ -75,59 +78,56 @@ RocketChat.callbacks.remove = function(hookName, id) {

RocketChat.callbacks.run = function(hook, item, constant) {
const callbacks = RocketChat.callbacks[hook];
if (callbacks && callbacks.length) {
if (!callbacks || !callbacks.length) {
return item;
}

let rocketchatHooksEnd;
if (Meteor.isServer) {
rocketchatHooksEnd = RocketChat.metrics.rocketchatHooks.startTimer({hook, callbacks_length: callbacks.length});
}

let rocketchatHooksEnd;
let totalTime = 0;
const result = callbacks.reduce(function(result, callback) {
let rocketchatCallbacksEnd;
if (Meteor.isServer) {
rocketchatHooksEnd = RocketChat.metrics.rocketchatHooks.startTimer({hook, callbacks_length: callbacks.length});
rocketchatCallbacksEnd = RocketChat.metrics.rocketchatCallbacks.startTimer({hook, callback: callback.id});
}

let totalTime = 0;
const result = _.sortBy(callbacks, function(callback) {
return callback.priority || RocketChat.callbacks.priority.MEDIUM;
}).reduce(function(result, callback) {
let rocketchatCallbacksEnd;
if (Meteor.isServer) {
rocketchatCallbacksEnd = RocketChat.metrics.rocketchatCallbacks.startTimer({hook, callback: callback.id});
}
let time = 0;
if (RocketChat.callbacks.showTime === true || RocketChat.callbacks.showTotalTime === true) {
time = Date.now();
}
const callbackResult = callback(result, constant);
if (RocketChat.callbacks.showTime === true || RocketChat.callbacks.showTotalTime === true) {
const currentTime = Date.now() - time;
totalTime += currentTime;
if (RocketChat.callbacks.showTime === true) {
if (Meteor.isServer) {
rocketchatCallbacksEnd();
RocketChat.statsTracker.timing('callbacks.time', currentTime, [`hook:${ hook }`, `callback:${ callback.id }`]);
} else {
let stack = callback.stack && typeof callback.stack.split === 'function' && callback.stack.split('\n');
stack = stack && stack[2] && (stack[2].match(/\(.+\)/)||[])[0];
console.log(String(currentTime), hook, callback.id, stack);
}
const time = RocketChat.callbacks.showTime === true || RocketChat.callbacks.showTotalTime === true ? Date.now() : 0;

const callbackResult = callback(result, constant);

if (RocketChat.callbacks.showTime === true || RocketChat.callbacks.showTotalTime === true) {
const currentTime = Date.now() - time;
totalTime += currentTime;
if (RocketChat.callbacks.showTime === true) {
if (Meteor.isServer) {
rocketchatCallbacksEnd();
RocketChat.statsTracker.timing('callbacks.time', currentTime, [`hook:${ hook }`, `callback:${ callback.id }`]);
} else {
let stack = callback.stack && typeof callback.stack.split === 'function' && callback.stack.split('\n');
stack = stack && stack[2] && (stack[2].match(/\(.+\)/)||[])[0];
console.log(String(currentTime), hook, callback.id, stack);
}
}
return (typeof callbackResult === 'undefined') ? result : callbackResult;
}, item);
}
return (typeof callbackResult === 'undefined') ? result : callbackResult;
}, item);

if (Meteor.isServer) {
rocketchatHooksEnd();
}

if (RocketChat.callbacks.showTotalTime === true) {
if (Meteor.isServer) {
rocketchatHooksEnd();
RocketChat.statsTracker.timing('callbacks.totalTime', totalTime, [`hook:${ hook }`]);
} else {
console.log(`${ hook }:`, totalTime);
}
}

if (RocketChat.callbacks.showTotalTime === true) {
if (Meteor.isServer) {
RocketChat.statsTracker.timing('callbacks.totalTime', totalTime, [`hook:${ hook }`]);
} else {
console.log(`${ hook }:`, totalTime);
}
}
return result;

return result;
} else {
return item;
}
};


Expand All @@ -142,9 +142,8 @@ RocketChat.callbacks.runAsync = function(hook, item, constant) {
const callbacks = RocketChat.callbacks[hook];
if (Meteor.isServer && callbacks && callbacks.length) {
Meteor.defer(function() {
_.sortBy(callbacks, (callback) => callback.priority || RocketChat.callbacks.priority.MEDIUM).forEach((callback) => callback(item, constant));
callbacks.forEach(callback => callback(item, constant));
});
} else {
return item;
}
return item;
};
26 changes: 9 additions & 17 deletions packages/rocketchat-lib/lib/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ RocketChat.promises.priority = {
LOW: 1000
};

const getHook = hookName => RocketChat.promises[hookName] || [];

/*
* Add a callback function to a hook
Expand All @@ -26,14 +27,14 @@ RocketChat.promises.priority = {
*/

RocketChat.promises.add = function(hook, callback, p = RocketChat.promises.priority.MEDIUM, id) {
const priority = !_.isNumber(p) ? RocketChat.promises.priority.MEDIUM : p;
callback.priority = priority;
callback.priority = _.isNumber(p) ? p : RocketChat.promises.priority.MEDIUM;
callback.id = id || Random.id();
RocketChat.promises[hook] = RocketChat.promises[hook] || [];
RocketChat.promises[hook] = getHook(hook);
if (RocketChat.promises[hook].find(cb => cb.id === callback.id)) {
return;
}
RocketChat.promises[hook].push(callback);
RocketChat.promises[hook] = _.sortBy(RocketChat.promises[hook], callback => callback.priority || RocketChat.promises.priority.MEDIUM);
};


Expand All @@ -43,8 +44,8 @@ RocketChat.promises.add = function(hook, callback, p = RocketChat.promises.prior
* @param {string} id - The callback's id
*/

RocketChat.promises.remove = function(hookName, id) {
RocketChat.promises[hookName] = _.reject(RocketChat.promises[hookName], (callback) => callback.id === id);
RocketChat.promises.remove = function(hook, id) {
RocketChat.promises[hook] = getHook(hook).filter(callback => callback.id !== id);
};


Expand All @@ -57,16 +58,11 @@ RocketChat.promises.remove = function(hookName, id) {
*/

RocketChat.promises.run = function(hook, item, constant) {
let callbacks = RocketChat.promises[hook];
const callbacks = RocketChat.promises[hook];
if (callbacks == null || callbacks.length === 0) {
return Promise.resolve(item);
}
callbacks = _.sortBy(callbacks, (callback) => callback.priority || RocketChat.promises.priority.MEDIUM);
return callbacks.reduce(function(previousPromise, callback) {
return new Promise(function(resolve, reject) {
return previousPromise.then((result) => callback(result, constant).then(resolve, reject));
});
}, Promise.resolve(item));
return callbacks.reduce((previousPromise, callback) => previousPromise.then(result => callback(result, constant)), Promise.resolve(item));
};


Expand All @@ -82,9 +78,5 @@ RocketChat.promises.runAsync = function(hook, item, constant) {
if (!Meteor.isServer || callbacks == null || callbacks.length === 0) {
return item;
}
Meteor.defer(() => {
_.sortBy(callbacks, (callback) => callback.priority || RocketChat.promises.priority.MEDIUM).forEach(function(callback) {
callback(item, constant);
});
});
Meteor.defer(() => callbacks.forEach(callback => callback(item, constant)));
};