Skip to content

Commit

Permalink
Avoid blocking other requests while validating large output
Browse files Browse the repository at this point in the history
  • Loading branch information
slickmb committed Jun 7, 2017
1 parent 72ef518 commit 62b0ee9
Showing 1 changed file with 21 additions and 9 deletions.
30 changes: 21 additions & 9 deletions lib/responseHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ responseHelper._enforceSchemaOnArray = (items, schema, callback) => {
if (!(items instanceof Array)) {
items = [ items ]
}
async.map(items, (item, done) => responseHelper._enforceSchemaOnObject(item, schema, done), (err, results) => {
// the validation process can take a lengthy amount of time when processing large responses.
// to prevent other requests from being blocked by this syncronous process, we break it up using
// setImmediate (see _enforceSchemaOnObject below), and force this map to run in series instead of in parallel.
// It really will not make much of a difference to individual requests, but
// splitting it up this way makes a HUGE difference if a small request arrives on the server while a large request's
// output is still being validated.
async.mapSeries(items, (item, done) => responseHelper._enforceSchemaOnObject(item, schema, done), (err, results) => {
if (err) return callback(err)

results = results.filter(result => !!result)
Expand All @@ -30,15 +36,21 @@ responseHelper._enforceSchemaOnArray = (items, schema, callback) => {
}

responseHelper._enforceSchemaOnObject = (item, schema, callback) => {
debug.validationOutput(JSON.stringify(item))
Joi.validate(item, schema, (err, sanitisedItem) => {
if (err) {
debug.validationError(err.message, JSON.stringify(item))
return callback(null, null)
}
setImmediate(() => {
debug.validationOutput(JSON.stringify(item))
Joi.validate(item, schema, (err, sanitisedItem) => {
if (err) {
debug.validationError(err.message, JSON.stringify(item))
// is silently dropping an output just because it doesn't validate really the right thing to do here?
// if a dev isn't watching their logs carefully, this could cause unexpected output.
// that said, Joi.validate does do some nice things, like normalizing data types and setting defaults, etc.
// not sure what the right answer is here.
return callback(null, null)
}

const dataItem = responseHelper._generateDataItem(sanitisedItem, schema)
return callback(null, dataItem)
const dataItem = responseHelper._generateDataItem(sanitisedItem, schema)
return callback(null, dataItem)
})
})
}

Expand Down

0 comments on commit 62b0ee9

Please sign in to comment.