Improved database perf

Transfarring some of the computations to the server. Things seem to work
now.
This commit is contained in:
Thomas FORGIONE 2015-09-28 15:14:59 +02:00
parent f0a444bab7
commit 8025de6b3b
3 changed files with 112 additions and 48 deletions

View File

@ -553,9 +553,10 @@ DBReq.UserCreator.prototype.finish = function() {
* @memberof DBReq * @memberof DBReq
* @constructor * @constructor
*/ */
DBReq.ExpCreator = function(userId, finishAction) { DBReq.ExpCreator = function(userId, experiments, finishAction) {
this.finishAction = finishAction; this.finishAction = finishAction;
this.userId = userId; this.userId = userId;
this.experiments = experiments;
this.finalResult = {}; this.finalResult = {};
// Connect to db // Connect to db
@ -574,6 +575,20 @@ DBReq.ExpCreator = function(userId, finishAction) {
}); });
}; };
function predicate(line) {
return function(elt, idx, arr) {
console.log(elt.recommendationStyle, line.recommendationStyle);
return (
elt.recommendationStyle.trim() === line.recommendationStyle.trim() ||
line.id === elt.coinCombinationId
);
};
}
/** /**
* Executes the SQL request and calls the callback * Executes the SQL request and calls the callback
*/ */
@ -582,7 +597,7 @@ DBReq.ExpCreator.prototype.execute = function() {
var self = this; var self = this;
this.client.query( this.client.query(
"SELECT DISTINCT \n" + "SELECT DISTINCT \n" +
" RecommendationStyle.name, \n" + " RecommendationStyle.name AS \"recommendationStyle\", \n" +
" CoinCombination.scene_id AS \"sceneId\", \n" + " CoinCombination.scene_id AS \"sceneId\", \n" +
" CoinCombination.id, \n" + " CoinCombination.id, \n" +
" coin_1 AS coin1, \n" + " coin_1 AS coin1, \n" +
@ -601,47 +616,68 @@ DBReq.ExpCreator.prototype.execute = function() {
" Other.id = Experiment.user_id AND\n" + " Other.id = Experiment.user_id AND\n" +
" Other.rating = U.rating AND\n" + " Other.rating = U.rating AND\n" +
" Other.id != U.id AND\n" + " Other.id != U.id AND\n" +
" U.id = $1 AND\n" + " U.id = $1 \n" +
" RecommendationStyle.name NOT IN (\n" + "EXCEPT \n" +
" SELECT DISTINCT Experiment.recommendation_style\n" + "SELECT DISTINCT \n" +
" FROM CoinCombination, Experiment, Users U, Users Other\n" + " Experiment.recommendation_style AS \"recommendationStyle\", \n" +
" WHERE\n" + " CoinCombination.scene_id AS \"sceneId\", \n" +
" CoinCombination.id = Experiment.coin_combination_id AND\n" + " CoinCombination.id, \n" +
" Other.id = Experiment.user_id AND\n" + " coin_1 AS coin1, \n" +
" Other.rating = U.rating AND\n" + " coin_2 AS coin2, \n" +
" Other.id != U.id AND\n" + " coin_3 AS coin3, \n" +
" CoinCombination.scene_id = Scene.id\n" + " coin_4 AS coin4, \n" +
" ) AND\n" + " coin_5 AS coin5, \n" +
" RecommendationStyle.name NOT IN (\n" + " coin_6 AS coin6, \n" +
" SELECT DISTINCT Experiment.recommendation_style\n" + " coin_7 AS coin7, \n" +
" FROM Experiment\n" + " coin_8 AS coin8\n" +
" WHERE Experiment.user_id = $1 AND Experiment.recommendation_style != ''\n" + "FROM CoinCombination, Experiment\n" +
" ) AND\n" + "WHERE\n" +
" CoinCombination.scene_id NOT IN (\n" + " CoinCombination.id = Experiment.coin_combination_id;",
" SELECT DISTINCT scene_id\n" +
" FROM Experiment, CoinCombination\n" +
" WHERE Experiment.coin_combination_id = CoinCombination.id AND Experiment.user_id = $1\n" +
" )\n" +
"LIMIT 1;",
[self.userId], [self.userId],
function(err, result) { function(err, result) {
if (err !== null) { if (err !== null) {
Log.dberror(err + ' in ExpCreator first request'); Log.dberror(err + ' in ExpCreator first request');
} }
if (result.rows.length > 0) {
var line, found = false;
while ((line = result.rows.shift()) !== undefined) {
if (line === undefined) {
break;
}
// Look for an experiment impossible
var elt = self.experiments.find(predicate(line));
// console.log(elt);
// Line is a valid experiment
if (elt === undefined) {
found = true;
break;
}
}
if (found) {
// Set the result // Set the result
self.finalResult.coinCombinationId = result.rows[0].id; self.finalResult.coinCombinationId = line.id;
self.finalResult.sceneId = result.rows[0].sceneId; self.finalResult.sceneId = line.sceneId;
self.finalResult.recommendationStyle = result.rows[0].name; self.finalResult.recommendationStyle = line.recommendationStyle;
self.finalResult.coins = [ self.finalResult.coins = [
result.rows[0].coin1, line.coin1,
result.rows[0].coin2, line.coin2,
result.rows[0].coin3, line.coin3,
result.rows[0].coin4, line.coin4,
result.rows[0].coin5, line.coin5,
result.rows[0].coin6, line.coin6,
result.rows[0].coin7, line.coin7,
result.rows[0].coin8 line.coin8
]; ];
// There is a suggested experiment : create it // There is a suggested experiment : create it
@ -649,7 +685,7 @@ DBReq.ExpCreator.prototype.execute = function() {
"INSERT INTO Experiment(user_id, coin_combination_id, recommendation_style)\n" + "INSERT INTO Experiment(user_id, coin_combination_id, recommendation_style)\n" +
"VALUES($1,$2,$3)\n" + "VALUES($1,$2,$3)\n" +
"RETURNING id", "RETURNING id",
[self.userId, result.rows[0].id, result.rows[0].name], [self.userId, line.id, line.recommendationStyle],
function(err, result) { function(err, result) {
if (err !== null) { if (err !== null) {
Log.dberror(err + ' in ExpCreator second request (with suggested experiment)'); Log.dberror(err + ' in ExpCreator second request (with suggested experiment)');
@ -950,7 +986,8 @@ DBReq.LastExpGetter.prototype.execute = function() {
' coin_6, \n' + ' coin_6, \n' +
' coin_7, \n' + ' coin_7, \n' +
' coin_8, \n' + ' coin_8, \n' +
' Experiment.recommendation_style AS "recommendationStyle" \n' + ' Experiment.recommendation_style AS "recommendationStyle", \n' +
' CoinCombination.id as "coinCombinationId" \n' +
'FROM Experiment, CoinCombination \n' + 'FROM Experiment, CoinCombination \n' +
'WHERE Experiment.coin_combination_id = CoinCombination.id \n' + 'WHERE Experiment.coin_combination_id = CoinCombination.id \n' +
' AND Experiment.user_id = $1 \n' + ' AND Experiment.user_id = $1 \n' +
@ -970,6 +1007,7 @@ DBReq.LastExpGetter.prototype.execute = function() {
result.rows[0].coin_7, result.rows[0].coin_7,
result.rows[0].coin_8 result.rows[0].coin_8
]; ];
self.finalResult.coinCombinationId = result.rows[0].coinCombinationId;
self.finish(); self.finish();
} }
); );
@ -980,8 +1018,13 @@ DBReq.LastExpGetter.prototype.finish = function() {
this.client = null; this.client = null;
this.release = null; this.release = null;
this.finishAction(this.finalResult.sceneId, this.finalResult.recommendationStyle, this.finalResult.coins); this.finishAction(
} this.finalResult.sceneId,
this.finalResult.coinCombinationId,
this.finalResult.recommendationStyle,
this.finalResult.coins
);
};
/** /**
* Class that gets the info from all experiment * Class that gets the info from all experiment
@ -1152,8 +1195,8 @@ DBReq.createUser = function(workerId, age, male, rating, lastTime, callback) {
* @param sceneId {Number} id of the scene on which the experiment is * @param sceneId {Number} id of the scene on which the experiment is
* @param callback {function} callback called on the new experiment id * @param callback {function} callback called on the new experiment id
*/ */
DBReq.createExp = function(id, callback) { DBReq.createExp = function(id, experiments, callback) {
new DBReq.ExpCreator(id, callback); new DBReq.ExpCreator(id, experiments, callback);
}; };
DBReq.createTutorial = function(id, callback) { DBReq.createTutorial = function(id, callback) {

View File

@ -26,12 +26,16 @@ var sceneToFunction = function(scene) {
module.exports.game = function(req, res) { module.exports.game = function(req, res) {
req.session.experiments = req.session.experiments || [];
req.session.save();
db.checkUserId(req.session.userId, function(ok) { db.checkUserId(req.session.userId, function(ok) {
if (ok) { if (ok) {
db.createExp( db.createExp(
req.session.userId, req.session.userId,
req.session.experiments,
function(expId, coinCombinationId, sceneId, recommendationStyle, coins) { function(expId, coinCombinationId, sceneId, recommendationStyle, coins) {
// if (expId === undefined) { // if (expId === undefined) {
@ -73,12 +77,22 @@ module.exports.play = function(req, res) {
} }
db.getLastExp(req.session.userId, function(sceneId, recoStyle, coins) { req.session.experiments = req.session.experiments || [];
db.getLastExp(req.session.userId, function(sceneId, coinId, recoStyle, coins) {
res.locals.scene = sceneToFunction(sceneId); res.locals.scene = sceneToFunction(sceneId);
res.locals.recommendationStyle= recoStyle; res.locals.recommendationStyle= recoStyle;
res.locals.coins = coins; res.locals.coins = coins;
req.session.experiments.push({
sceneId: sceneId,
recommendationStyle: recoStyle,
coinCombinationId : coinId
});
req.session.save();
// Prepare next experiment // Prepare next experiment
module.exports.game(req, null); module.exports.game(req, null);
@ -113,6 +127,13 @@ module.exports.replay = function(req, res, next) {
// Get id parameter // Get id parameter
res.locals.id = tools.filterInt(req.params.id); res.locals.id = tools.filterInt(req.params.id);
if (res.locals.id <= 0) {
var err = new Error("This replay does not exist");
err.status = 404;
next(err);
return;
}
db.checkExpId(res.locals.id, function(sceneId) { db.checkExpId(res.locals.id, function(sceneId) {
if (sceneId === null) { if (sceneId === null) {
var err = new Error("This replay does not exist"); var err = new Error("This replay does not exist");

10
load.js
View File

@ -16,7 +16,7 @@ var casper = require('casper').create({
waitTimeout: 100000 waitTimeout: 100000
}); });
var limit = 100; var limit = 1;
casper.start('http://localhost:4000/'); casper.start('http://localhost:4000/');
@ -42,10 +42,10 @@ for (var i = 0; i < limit; i++) {
// }, true); // }, true);
this.thenOpen('http://localhost:4000/prototype/game'); this.thenOpen('http://localhost:4000/prototype/tutorial');
this.thenOpen('http://localhost:4000/prototype/game'); this.thenOpen('http://localhost:4000/prototype/play');
this.thenOpen('http://localhost:4000/prototype/game'); this.thenOpen('http://localhost:4000/prototype/play');
this.thenOpen('http://localhost:4000/prototype/game'); this.thenOpen('http://localhost:4000/prototype/play');
this.thenOpen('http://localhost:4000/logout'); this.thenOpen('http://localhost:4000/logout');