mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-30 02:55:43 -05:00
Added one-minute in-memory server caching for a bunch of common queries.
This commit is contained in:
parent
9b34d4e166
commit
b4e9ee67f0
8 changed files with 51 additions and 39 deletions
|
@ -64,7 +64,7 @@ module.exports = class LadderView extends RootView
|
||||||
@insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
|
@insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
|
||||||
@insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
|
@insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
|
||||||
@insertSubView(@simulateTab = new SimulateTabView())
|
@insertSubView(@simulateTab = new SimulateTabView())
|
||||||
@refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 20 * 1000)
|
@refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 60 * 1000)
|
||||||
hash = document.location.hash[1..] if document.location.hash
|
hash = document.location.hash[1..] if document.location.hash
|
||||||
if hash and not (hash in ['my-matches', 'simulate', 'ladder', 'prizes', 'rules', 'winners'])
|
if hash and not (hash in ['my-matches', 'simulate', 'ladder', 'prizes', 'rules', 'winners'])
|
||||||
@showPlayModal(hash) if @sessions.loaded
|
@showPlayModal(hash) if @sessions.loaded
|
||||||
|
|
55
package.json
55
package.json
|
@ -38,36 +38,37 @@
|
||||||
"multiplayer"
|
"multiplayer"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "~3.0.6",
|
|
||||||
"winston": "0.6.x",
|
|
||||||
"passport": "0.1.x",
|
|
||||||
"passport-local": "0.1.x",
|
|
||||||
"moment": "~2.5.0",
|
|
||||||
"mongoose": "3.8.x",
|
|
||||||
"request": "2.12.x",
|
|
||||||
"tv4": "~1.0.16",
|
|
||||||
"lodash": "~2.4.1",
|
|
||||||
"underscore.string": "2.3.x",
|
|
||||||
"async": "0.2.x",
|
|
||||||
"connect": "2.7.x",
|
|
||||||
"coffee-script": "1.9.x",
|
|
||||||
"graceful-fs": "~2.0.1",
|
|
||||||
"node-force-domain": "~0.1.0",
|
|
||||||
"mailchimp-api": "2.0.x",
|
|
||||||
"express-useragent": "~0.0.9",
|
|
||||||
"gridfs-stream": "0.4.x",
|
|
||||||
"stream-buffers": "0.2.x",
|
|
||||||
"sendwithus": "2.1.x",
|
|
||||||
"aws-sdk": "~2.0.0",
|
|
||||||
"bayesian-battle": "0.0.x",
|
|
||||||
"redis": "",
|
|
||||||
"webworker-threads": "~0.5.5",
|
|
||||||
"node-gyp": "~0.13.0",
|
|
||||||
"aether": "~0.3.0",
|
|
||||||
"JASON": "~0.1.3",
|
"JASON": "~0.1.3",
|
||||||
"JQDeferred": "~2.1.0",
|
"JQDeferred": "~2.1.0",
|
||||||
|
"aether": "~0.3.0",
|
||||||
|
"async": "0.2.x",
|
||||||
|
"aws-sdk": "~2.0.0",
|
||||||
|
"bayesian-battle": "0.0.x",
|
||||||
|
"coffee-script": "1.9.x",
|
||||||
|
"connect": "2.7.x",
|
||||||
|
"express": "~3.0.6",
|
||||||
|
"express-useragent": "~0.0.9",
|
||||||
|
"graceful-fs": "~2.0.1",
|
||||||
|
"gridfs-stream": "0.4.x",
|
||||||
"jsondiffpatch": "0.1.17",
|
"jsondiffpatch": "0.1.17",
|
||||||
"stripe": "~2.9.0"
|
"lodash": "~2.4.1",
|
||||||
|
"mailchimp-api": "2.0.x",
|
||||||
|
"moment": "~2.5.0",
|
||||||
|
"mongoose": "3.8.x",
|
||||||
|
"mongoose-cache": "https://github.com/nwinter/mongoose-cache/tarball/master",
|
||||||
|
"node-force-domain": "~0.1.0",
|
||||||
|
"node-gyp": "~0.13.0",
|
||||||
|
"passport": "0.1.x",
|
||||||
|
"passport-local": "0.1.x",
|
||||||
|
"redis": "",
|
||||||
|
"request": "2.12.x",
|
||||||
|
"sendwithus": "2.1.x",
|
||||||
|
"stream-buffers": "0.2.x",
|
||||||
|
"stripe": "~2.9.0",
|
||||||
|
"tv4": "~1.0.16",
|
||||||
|
"underscore.string": "2.3.x",
|
||||||
|
"webworker-threads": "~0.5.5",
|
||||||
|
"winston": "0.6.x"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"auto-reload-brunch": "> 1.0 < 1.8",
|
"auto-reload-brunch": "> 1.0 < 1.8",
|
||||||
|
|
|
@ -2,6 +2,7 @@ config = require '../../server_config'
|
||||||
winston = require 'winston'
|
winston = require 'winston'
|
||||||
mongoose = require 'mongoose'
|
mongoose = require 'mongoose'
|
||||||
Grid = require 'gridfs-stream'
|
Grid = require 'gridfs-stream'
|
||||||
|
mongooseCache = require 'mongoose-cache'
|
||||||
|
|
||||||
global.testing = testing = '--unittest' in process.argv
|
global.testing = testing = '--unittest' in process.argv
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ module.exports.connect = () ->
|
||||||
mongoose.connect address
|
mongoose.connect address
|
||||||
mongoose.connection.once 'open', -> Grid.gfs = Grid(mongoose.connection.db, mongoose.mongo)
|
mongoose.connection.once 'open', -> Grid.gfs = Grid(mongoose.connection.db, mongoose.mongo)
|
||||||
|
|
||||||
|
mongooseCache.install(mongoose, {max: 200, maxAge: 1 * 60 * 1000, debug: false})
|
||||||
|
|
||||||
module.exports.generateMongoConnectionString = ->
|
module.exports.generateMongoConnectionString = ->
|
||||||
if not testing and config.mongo.mongoose_replica_string
|
if not testing and config.mongo.mongoose_replica_string
|
||||||
|
|
|
@ -164,6 +164,7 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
{$match: {'levelID': slug, 'submitted': true, 'team': req.query.team}}
|
{$match: {'levelID': slug, 'submitted': true, 'team': req.query.team}}
|
||||||
{$project: {totalScore: 1, _id: 0}}
|
{$project: {totalScore: 1, _id: 0}}
|
||||||
]
|
]
|
||||||
|
#query.cache() # TODO: implement caching for aggregates
|
||||||
|
|
||||||
query.exec (err, data) =>
|
query.exec (err, data) =>
|
||||||
if err? then return @sendDatabaseError res, err
|
if err? then return @sendDatabaseError res, err
|
||||||
|
@ -199,6 +200,7 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
.limit(req.query.limit)
|
.limit(req.query.limit)
|
||||||
.sort(sortParameters)
|
.sort(sortParameters)
|
||||||
.select(selectProperties.join ' ')
|
.select(selectProperties.join ' ')
|
||||||
|
query.cache() if sessionsQueryParameters.totalScore.$lt is 1000000
|
||||||
|
|
||||||
query.exec (err, resultSessions) =>
|
query.exec (err, resultSessions) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
|
@ -269,6 +271,7 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
query = Level.findOne(findParameters)
|
query = Level.findOne(findParameters)
|
||||||
.select(selectString)
|
.select(selectString)
|
||||||
.lean()
|
.lean()
|
||||||
|
.cache()
|
||||||
|
|
||||||
query.exec (err, level) =>
|
query.exec (err, level) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
|
@ -280,17 +283,19 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
majorVersion: level.version.major
|
majorVersion: level.version.major
|
||||||
submitted: true
|
submitted: true
|
||||||
|
|
||||||
query = Session.find(sessionsQueryParameters).distinct('team')
|
query = Session.find(sessionsQueryParameters).distinct('team').cache()
|
||||||
query.exec (err, teams) =>
|
query.exec (err, teams) =>
|
||||||
return @sendDatabaseError res, err if err? or not teams
|
return @sendDatabaseError res, err if err? or not teams
|
||||||
findTop20Players = (sessionQueryParams, team, cb) ->
|
findTop20Players = (sessionQueryParams, team, cb) ->
|
||||||
sessionQueryParams['team'] = team
|
sessionQueryParams['team'] = team
|
||||||
Session.aggregate [
|
aggregate = Session.aggregate [
|
||||||
{$match: sessionQueryParams}
|
{$match: sessionQueryParams}
|
||||||
{$project: {'totalScore': 1}}
|
{$project: {'totalScore': 1}}
|
||||||
{$sort: {'totalScore': -1}}
|
{$sort: {'totalScore': -1}}
|
||||||
{$limit: 20}
|
{$limit: 20}
|
||||||
], cb
|
]
|
||||||
|
#aggregate.cache() # TODO: implement caching for aggregates
|
||||||
|
aggregate.exec cb
|
||||||
|
|
||||||
async.map teams, findTop20Players.bind(@, sessionsQueryParameters), (err, map) =>
|
async.map teams, findTop20Players.bind(@, sessionsQueryParameters), (err, map) =>
|
||||||
if err? then return @sendDatabaseError(res, err)
|
if err? then return @sendDatabaseError(res, err)
|
||||||
|
|
|
@ -70,6 +70,8 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
|
||||||
if limit? and limit < 1000
|
if limit? and limit < 1000
|
||||||
q.limit(limit)
|
q.limit(limit)
|
||||||
|
|
||||||
|
q.cache()
|
||||||
|
|
||||||
q.exec (err, documents) =>
|
q.exec (err, documents) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
documents = (@formatEntity(req, doc) for doc in documents)
|
documents = (@formatEntity(req, doc) for doc in documents)
|
||||||
|
|
|
@ -138,7 +138,7 @@ module.exports.getTwoGames = (req, res) ->
|
||||||
'submitted': true
|
'submitted': true
|
||||||
'team': 'humans'
|
'team': 'humans'
|
||||||
selection = 'team totalScore transpiledCode submittedCodeLanguage teamSpells levelID creatorName creator submitDate'
|
selection = 'team totalScore transpiledCode submittedCodeLanguage teamSpells levelID creatorName creator submitDate'
|
||||||
LevelSession.count queryParams, (err, numberOfHumans) =>
|
LevelSession.count(queryParams).cache().exec (err, numberOfHumans) =>
|
||||||
if err? then return errors.serverError(res, 'Couldn\'t get the number of human games')
|
if err? then return errors.serverError(res, 'Couldn\'t get the number of human games')
|
||||||
unless numberOfHumans
|
unless numberOfHumans
|
||||||
res.send(204, 'No games to score.')
|
res.send(204, 'No games to score.')
|
||||||
|
@ -149,7 +149,7 @@ module.exports.getTwoGames = (req, res) ->
|
||||||
'levelID': levelID
|
'levelID': levelID
|
||||||
'submitted': true
|
'submitted': true
|
||||||
'team': 'ogres'
|
'team': 'ogres'
|
||||||
LevelSession.count ogreCountParams, (err, numberOfOgres) =>
|
LevelSession.count(ogreCountParams).cache().exec (err, numberOfOgres) =>
|
||||||
if err? then return errors.serverError(res, 'Couldn\'t get the number of ogre games')
|
if err? then return errors.serverError(res, 'Couldn\'t get the number of ogre games')
|
||||||
unless numberOfOgres
|
unless numberOfOgres
|
||||||
res.send(204, 'No games to score.')
|
res.send(204, 'No games to score.')
|
||||||
|
|
|
@ -172,11 +172,12 @@ UserHandler = class UserHandler extends Handler
|
||||||
getSimulatorLeaderboard: (req, res) ->
|
getSimulatorLeaderboard: (req, res) ->
|
||||||
queryParameters = @getSimulatorLeaderboardQueryParameters(req)
|
queryParameters = @getSimulatorLeaderboardQueryParameters(req)
|
||||||
leaderboardQuery = User.find(queryParameters.query).select('name simulatedBy simulatedFor').sort({'simulatedBy': queryParameters.sortOrder}).limit(queryParameters.limit)
|
leaderboardQuery = User.find(queryParameters.query).select('name simulatedBy simulatedFor').sort({'simulatedBy': queryParameters.sortOrder}).limit(queryParameters.limit)
|
||||||
|
leaderboardQuery.cache() if req.query.scoreOffset is -1
|
||||||
leaderboardQuery.exec (err, otherUsers) ->
|
leaderboardQuery.exec (err, otherUsers) ->
|
||||||
otherUsers = _.reject otherUsers, _id: req.user._id if req.query.scoreOffset isnt -1
|
otherUsers = _.reject otherUsers, _id: req.user._id if req.query.scoreOffset isnt -1
|
||||||
otherUsers ?= []
|
otherUsers ?= []
|
||||||
res.send(otherUsers)
|
res.send(otherUsers)
|
||||||
res.end()
|
res.end()
|
||||||
|
|
||||||
getMySimulatorLeaderboardRank: (req, res) ->
|
getMySimulatorLeaderboardRank: (req, res) ->
|
||||||
req.query.order = 1
|
req.query.order = 1
|
||||||
|
@ -229,12 +230,12 @@ UserHandler = class UserHandler extends Handler
|
||||||
for prop, val of obj
|
for prop, val of obj
|
||||||
user.set(prop, undefined) unless prop is '_id'
|
user.set(prop, undefined) unless prop is '_id'
|
||||||
user.set('deleted', true)
|
user.set('deleted', true)
|
||||||
|
|
||||||
# Hack to get saving of Users to work. Probably should replace these props with strings
|
# Hack to get saving of Users to work. Probably should replace these props with strings
|
||||||
# so that validation doesn't get hung up on Date objects in the documents.
|
# so that validation doesn't get hung up on Date objects in the documents.
|
||||||
delete obj.dateCreated
|
delete obj.dateCreated
|
||||||
|
|
||||||
user.save (err) =>
|
user.save (err) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
@sendNoContent res
|
@sendNoContent res
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ setupErrorMiddleware = (app) ->
|
||||||
hipchat.sendHipChatMessage(message, ['tower'], {papertrail: true})
|
hipchat.sendHipChatMessage(message, ['tower'], {papertrail: true})
|
||||||
else
|
else
|
||||||
next(err)
|
next(err)
|
||||||
|
|
||||||
setupExpressMiddleware = (app) ->
|
setupExpressMiddleware = (app) ->
|
||||||
if config.isProduction
|
if config.isProduction
|
||||||
express.logger.format('prod', productionLogging)
|
express.logger.format('prod', productionLogging)
|
||||||
|
|
Loading…
Reference in a new issue