Merge branch 'master' into production

This commit is contained in:
Nick Winter 2016-03-14 16:58:28 -07:00
commit 9404dcdb32
6 changed files with 65 additions and 34 deletions

View file

@ -28,12 +28,11 @@ module.exports = class LevelBus extends Bus
constructor: -> constructor: ->
super(arguments...) super(arguments...)
@changedSessionProperties = {} @changedSessionProperties = {}
highLoad = false saveDelay = window.serverConfig?.sessionSaveDelay
[wait, maxWait] = switch [wait, maxWait] = switch
when not application.isProduction() then [1, 5] # Save quickly in development. when not application.isProduction or not saveDelay then [1, 5] # Save quickly in development.
when not highLoad then [4, 10] # Save slowly when in production. when me.isAnonymous() then [saveDelay.anonymous.min, saveDelay.anonymous.max]
when not me.isAnonymous() then [10, 30] # Save even more slowly during HoC scaling. else [saveDelay.registered.min, saveDelay.registered.max]
else [20, 60] # Save super slowly if anonymous during HoC scaling.
@saveSession = _.debounce @reallySaveSession, wait * 1000, {maxWait: maxWait * 1000} @saveSession = _.debounce @reallySaveSession, wait * 1000, {maxWait: maxWait * 1000}
@playerIsIdle = false @playerIsIdle = false

View file

@ -5,14 +5,39 @@ module.exports = MandateSchema = {
additionalProperties: false additionalProperties: false
default: default:
simulationThroughputRatio: 1 simulationThroughputRatio: 1
properties: { sessionSaveDelay:
registered: {min: 4, max: 10}
anonymous: {min: 5, max: 15}
#registered: {min: 10, max: 30} # High load, like during HoC scaling
#anonymous: {min: 20, max: 60}
properties:
simulationThroughputRatio: simulationThroughputRatio:
name: 'Simulation Throughput Ratio' name: 'Simulation Throughput Ratio'
description: '0-1 fraction of requests for a match to simulate that should be granted.' description: '0-1 fraction of requests for a match to simulate that should be granted.'
type: 'number' type: 'number'
minimum: 0 minimum: 0
maximum: 1 maximum: 1
} sessionSaveDelay:
name: 'Session Save Delay'
description: 'How often we save level sessions after code changes--min and max wait in seconds.'
type: 'object'
properties:
registered:
description: 'How often to save for registered players.'
type: 'object'
additionalProperties: false
requiredProperties: ['min', 'max']
properties:
min: {type: 'number', minimum: 1, exclusiveMinimum: true, format: 'seconds'}
max: {type: 'number', minimum: 5, exclusiveMinimum: true, format: 'seconds'}
anonymous:
description: 'How often to save for anonymous players.'
type: 'object'
additionalProperties: false
requiredProperties: ['min', 'max']
properties:
min: {type: 'number', minimum: 1, exclusiveMinimum: true, format: 'seconds'}
max: {type: 'number', minimum: 5, exclusiveMinimum: true, format: 'seconds'}
} }
c.extendBasicProperties MandateSchema, 'Mandate' c.extendBasicProperties MandateSchema, 'Mandate'

View file

@ -5,11 +5,14 @@
margin-top: 20px margin-top: 20px
.login-btn .login-btn
margin-right: 10px margin-right: 0px
#create-account-btn
margin-left: 10px
#not-found-img #not-found-img
max-width: 20% max-width: 20%
margin: 20px 0 margin: 20px 0
#links-row #links-row
margin-top: 50px margin-top: 50px

View file

@ -18,12 +18,12 @@ if includeSpellList
.glyphicon.glyphicon-repeat .glyphicon.glyphicon-repeat
span.spl(data-i18n="play_level.reload") Reload span.spl(data-i18n="play_level.reload") Reload
if levelType !== 'hero' && levelType !== 'hero-ladder' && levelType !== 'hero-coop' if me.level() >= 15
.btn.btn-small.btn-illustrated.fullscreen-code(title=maximizeShortcutVerbose) .btn.btn-small.btn-illustrated.fullscreen-code(title=maximizeShortcutVerbose)
.glyphicon.glyphicon-fullscreen .glyphicon.glyphicon-fullscreen
.glyphicon.glyphicon-resize-small .glyphicon.glyphicon-resize-small
if codeLanguage === 'javascript' && levelType !== 'hero' && levelType !== 'hero-ladder' && levelType !== 'hero-coop' if codeLanguage === 'javascript' && me.level() >= 15
.btn.btn-small.btn-illustrated.beautify-code(title=beautifyShortcutVerbose) .btn.btn-small.btn-illustrated.beautify-code(title=beautifyShortcutVerbose)
.glyphicon.glyphicon-magnet .glyphicon.glyphicon-magnet

View file

@ -40,15 +40,13 @@ findLeads((err, leads) => {
console.error(err); console.error(err);
return; return;
} }
// TEMP // // TEMP
// for (const email in leads) { // for (const email in leads) {
// if (leads[email].coco_schoolName) { // console.log(email);
// console.log(email); // console.log(leads[email]);
// console.log(leads[email]); // break;
// // break;
// }
// } // }
// TEMP // // TEMP
log(`Num leads created ${numLeadsCreated}`); log(`Num leads created ${numLeadsCreated}`);
log("Script runtime: " + (new Date() - scriptStartTime)); log("Script runtime: " + (new Date() - scriptStartTime));
}); });
@ -187,7 +185,7 @@ function addIntercomData(leads, done) {
} }
function getUser(email) { function getUser(email) {
const options = { const options = {
url: `https://api.intercom.io/users?email=${email}`, url: `https://api.intercom.io/users?email=${encodeURIComponent(email)}`,
auth: { auth: {
user: intercomAppId, user: intercomAppId,
pass: intercomApiKey pass: intercomApiKey
@ -256,7 +254,7 @@ function updateLeads(leads, done) {
}); });
} }
function updateLead(email) { function updateLead(email) {
const url = `https://${closeIoApiKey}:X@app.close.io/api/v1/lead/?query=email_address:${email}`; const url = `https://${closeIoApiKey}:X@app.close.io/api/v1/lead/?query=email_address:${encodeURIComponent(email)}`;
request.get(url, (error, response, body) => { request.get(url, (error, response, body) => {
if (error) return done(error); if (error) return done(error);
const data = JSON.parse(body); const data = JSON.parse(body);

View file

@ -17,6 +17,7 @@ auth = require './server/routes/auth'
routes = require './server/routes' routes = require './server/routes'
UserHandler = require './server/users/user_handler' UserHandler = require './server/users/user_handler'
hipchat = require './server/hipchat' hipchat = require './server/hipchat'
Mandate = require './server/models/Mandate'
global.tv4 = require 'tv4' # required for TreemaUtils to work global.tv4 = require 'tv4' # required for TreemaUtils to work
global.jsondiffpatch = require 'jsondiffpatch' global.jsondiffpatch = require 'jsondiffpatch'
global.stripe = require('stripe')(config.stripe.secretKey) global.stripe = require('stripe')(config.stripe.secretKey)
@ -58,15 +59,15 @@ setupErrorMiddleware = (app) ->
err = new errors.UnprocessableEntity(err.response) err = new errors.UnprocessableEntity(err.response)
if err.code is 409 and err.response if err.code is 409 and err.response
err = new errors.Conflict(err.response) err = new errors.Conflict(err.response)
# TODO: Make all errors use this # TODO: Make all errors use this
if err instanceof errors.NetworkError if err instanceof errors.NetworkError
return res.status(err.code).send(err.toJSON()) return res.status(err.code).send(err.toJSON())
if err.status and 400 <= err.status < 500 if err.status and 400 <= err.status < 500
res.status(err.status).send("Error #{err.status}") res.status(err.status).send("Error #{err.status}")
return return
res.status(err.status ? 500).send(error: "Something went wrong!") res.status(err.status ? 500).send(error: "Something went wrong!")
message = "Express error: #{req.method} #{req.path}: #{err.message}" message = "Express error: #{req.method} #{req.path}: #{err.message}"
log.error "#{message}, stack: #{err.stack}" log.error "#{message}, stack: #{err.stack}"
@ -180,17 +181,22 @@ setupFallbackRouteToIndex = (app) ->
log.error "Error modifying main.html: #{err}" if err log.error "Error modifying main.html: #{err}" if err
# insert the user object directly into the html so the application can have it immediately. Sanitize </script> # insert the user object directly into the html so the application can have it immediately. Sanitize </script>
user = if req.user then JSON.stringify(UserHandler.formatEntity(req, req.user)).replace(/\//g, '\\/') else '{}' user = if req.user then JSON.stringify(UserHandler.formatEntity(req, req.user)).replace(/\//g, '\\/') else '{}'
data = data.replace '"serverConfigTag"', JSON.stringify Mandate.findOne({}).cache(5 * 60 * 1000).exec (err, mandate) ->
picoCTF: config.picoCTF, if err
production: config.isProduction log.error "Error getting mandate config: #{err}"
configData = {}
data = data.replace('"userObjectTag"', user) else
data = data.replace('"amActuallyTag"', JSON.stringify(req.session.amActually)) configData = _.omit mandate?.toObject() or {}, '_id'
res.header 'Cache-Control', 'no-cache, no-store, must-revalidate' configData.picoCTF = config.picoCTF
res.header 'Pragma', 'no-cache' configData.production = config.isProduction
res.header 'Expires', 0 data = data.replace '"serverConfigTag"', JSON.stringify configData
res.send 200, data data = data.replace('"userObjectTag"', user)
data = data.replace('"amActuallyTag"', JSON.stringify(req.session.amActually))
res.header 'Cache-Control', 'no-cache, no-store, must-revalidate'
res.header 'Pragma', 'no-cache'
res.header 'Expires', 0
res.send 200, data
setupFacebookCrossDomainCommunicationRoute = (app) -> setupFacebookCrossDomainCommunicationRoute = (app) ->
app.get '/channel.html', (req, res) -> app.get '/channel.html', (req, res) ->