diff --git a/src/controllers/user.js b/src/controllers/user.js index a44f5937da..f580f0f360 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -34,7 +34,7 @@ api.getContent = function(req, res, next) { --------------- */ -findTask = function(req, res) { +findTask = function(req, res, next) { return task = res.locals.user.tasks[req.params.id]; }; @@ -81,7 +81,7 @@ api.score = function(req, res, next) { var delta = user.ops.score({params:{id:task.id, direction:direction}}); user.save(function(err,saved){ - if (err) return res.json(500, {err: err}); + if (err) return next(err); // TODO this should be return {_v,task,stats,_tmp}, instead of merging everything togther at top-level response // However, this is the most commonly used API route, and changing it will mess with all 3rd party consumers. Bad idea :( res.json(200, _.extend({ @@ -193,7 +193,7 @@ api.update = function(req, res, next) { }); user.save(function(err) { if (!_.isEmpty(errors)) return res.json(401, {err: errors}); - if (err) return res.json(500, {err: err}); + if (err) return next(err); res.json(200, user); }); }; @@ -233,9 +233,9 @@ api.cron = function(req, res, next) { // api.reroll // Shared.ops // api.reset // Shared.ops -api['delete'] = function(req, res) { +api['delete'] = function(req, res, next) { res.locals.user.remove(function(err){ - if (err) return res.json(500,{err:err}); + if (err) return next(err); res.send(200); }) } @@ -254,11 +254,11 @@ api['delete'] = function(req, res) { ------------------------------------------------------------------------ */ -api.addTenGems = function(req, res) { +api.addTenGems = function(req, res, next) { var user = res.locals.user; user.balance += 2.5; user.save(function(err){ - if (err) return res.json(500,{err:err}); + if (err) return next(err); res.send(204); }) } @@ -268,7 +268,7 @@ api.addTenGems = function(req, res) { /* Setup Stripe response when posting payment */ -api.buyGems = function(req, res) { +api.buyGems = function(req, res, next) { var api_key = nconf.get('STRIPE_API_KEY'); var stripe = require("stripe")(api_key); var token = req.body.id; @@ -312,7 +312,7 @@ api.buyGems = function(req, res) { }); }; -api.cancelSubscription = function(req, res) { +api.cancelSubscription = function(req, res, next) { var api_key = nconf.get('STRIPE_API_KEY'); var stripe = require("stripe")(api_key); var user = res.locals.user; @@ -370,7 +370,7 @@ api.buyGemsPaypalIPN = function(req, res, next) { Spells ------------------------------------------------------------------------ */ -api.cast = function(req, res) { +api.cast = function(req, res, next) { var user = res.locals.user; var targetType = req.query.targetType; var targetId = req.query.targetId; @@ -381,7 +381,7 @@ api.cast = function(req, res) { var done = function(){ var err = arguments[0]; var saved = _.size(arguments == 3) ? arguments[2] : arguments[1]; - if (err) return res.json(500, {err:err}); + if (err) return next(err); res.json(saved); } @@ -445,12 +445,12 @@ _.each(shared.wrap({}).ops, function(op,k){ res.locals.user.ops[k](req,function(err, response){ // If we want to send something other than 500, pass err as {code: 200, message: "Not enough GP"} if (err) { - if (!err.code) return res.json(500,{err:err}); + if (!err.code) return next(err); if (err.code >= 400) return res.json(err.code,{err:err.message}); // In the case of 200s, they're friendly alert messages like "You're pet has hatched!" - still send the op } res.locals.user.save(function(err){ - if (err) return res.json(500,{err:err}); + if (err) return next(err); res.json(200,response); }) }) @@ -473,28 +473,33 @@ api.batchUpdate = function(req, res, next) { var oldSend = res.send; var oldJson = res.json; - var callOp = function(_req, cb) { - res.send = res.json = function(code, data) { - if (_.isNumber(code) && code >= 500) - return cb(code+": "+ (data.message ? data.message : data.err ? data.err : JSON.stringify(data))); - return cb(); - }; - api[_req.op](_req, res); - }; + // Stash user.save, we'll queue the save op till the end (so we don't overload the server) + var oldSave = user.save; + user.save = function(cb){cb(null,user)} - res.locals.ops = []; // Setup the array of functions we're going to call in parallel with async - var ops = _.transform(req.body, function(result, _req) { - if (!_.isEmpty(_req)) { - result.push(function(cb) { - res.locals.ops.push(_req); - callOp(_req, cb); - }); - } + res.locals.ops = []; + var ops = _.transform(req.body, function(m,_req){ + if (_.isEmpty(_req)) return; + m.push(function() { + var cb = arguments[arguments.length-1]; + res.locals.ops.push(_req); + res.send = res.json = function(code, data) { + if (_.isNumber(code) && code >= 500) + return cb(code+": "+ (data.message ? data.message : data.err ? data.err : JSON.stringify(data))); + return cb(); + }; + api[_req.op](_req, res, cb); + }); + }) + // Finally, save user at the end + .concat(function(){ + user.save = oldSave; + user.save(arguments[arguments.length-1]); }); // call all the operations, then return the user object to the requester - async.series(ops, function(err) { + async.waterfall(ops, function(err,user) { res.json = oldJson; res.send = oldSend; if (err) return next(err); diff --git a/src/middleware.js b/src/middleware.js index 781b6f7202..4450133f01 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -12,7 +12,7 @@ module.exports.apiThrottle = function(app) { catagories:{ normal: { // 2 req/s, but split as minutes - totalRequests: 120, + totalRequests: 80, every: 60000 } } diff --git a/src/utils.js b/src/utils.js index 1fb45587af..a4a44d52c2 100644 --- a/src/utils.js +++ b/src/utils.js @@ -49,21 +49,21 @@ module.exports.setupConfig = function(){ }; module.exports.crashWorker = function(server,mongoose) { - return function(err, req, res, next) { - if (!cluster.isMaster) { - // make sure we close down within 30 seconds - var killtimer = setTimeout(function() { - process.exit(1); - }, 30000); - // But don't keep the process open just for that! - killtimer.unref(); - // stop taking new requests. - server.close(); - mongoose.connection.close(); - cluster.worker.disconnect(); - } - next(err); - }; + return function(err, req, res, next) { + if (!cluster.isMaster) { + // make sure we close down within 30 seconds + var killtimer = setTimeout(function() { + process.exit(1); + }, 30000); + // But don't keep the process open just for that! + killtimer.unref(); + // stop taking new requests. + server.close(); + mongoose.connection.close(); + cluster.worker.disconnect(); + } + next(err); + }; } diff --git a/views/options/social/tavern.jade b/views/options/social/tavern.jade index 13d67e04a9..8eff0f5401 100644 --- a/views/options/social/tavern.jade +++ b/views/options/social/tavern.jade @@ -120,6 +120,6 @@ h3=env.t('tavernTalk') include ./chat-box .alert.alert-info - !=env.t('tavernAlert1') + ' ' + env.t('tavernAlert2') + '.' + !=env.t('tavernAlert1') + ' ' + env.t('tavernAlert2') + '.' ul.list-unstyled.tavern-chat include ./chat-message