Skip to content
This repository has been archived by the owner on Apr 20, 2019. It is now read-only.

Commit

Permalink
Merge pull request #67 from cadecairos/code-cleanup
Browse files Browse the repository at this point in the history
improve looping logic, reduce dependency on functions sharing variables, flatten code
  • Loading branch information
Christopher De Cairos committed May 28, 2016
2 parents b800167 + ed6137e commit b463282
Showing 1 changed file with 111 additions and 128 deletions.
239 changes: 111 additions & 128 deletions lib/batch.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,71 +18,55 @@ module.exports.config = function (settings) {
return {
handler: function (request, reply) {

const requests = [];
const payloads = [];
const resultsData = {
results: [],
resultsMap: []
};

const requests = [];
const requestRegex = /(?:\/)(?:\$(\d)+\.)?([^\/\$]*)/g; // /project/$1.project/tasks, does not allow using array responses

const payloads = [];
const payloadRegex = /^\$(\d+)(?:\.([^\s\$]*))?/;

// Validate requests

let errorMessage = null;
let i = 0;
let requestParts;
let result;

const il = request.payload.requests.length;
request.payload.requests.every((req, idx) => {

const parseRequest = function ($0, $1, $2) {
const requestParts = [];
const result = req.path.replace(internals.requestRegex, (match, p1, p2) => {

if ($1) {
if ($1 < i) {
requestParts.push({ type: 'ref', index: $1, value: $2 });
if (!p1) {
requestParts.push({ type: 'text', value: p2 });
return '';
}

errorMessage = 'Request reference is beyond array size: ' + i;
return $0;
}

requestParts.push({ type: 'text', value: $2 });
return '';
};

for ( ; i < il; ++i) {

// Break into parts
if (p1 < idx) {
requestParts.push({ type: 'ref', index: p1, value: p2 });
return '';
}

requestParts = [];
result = request.payload.requests[i].path.replace(requestRegex, parseRequest);
errorMessage = 'Request reference is beyond array size: ' + idx;
return match;
});

// Make sure entire string was processed (empty)

if (result === '') {
requests.push(requestParts);
}
else {
errorMessage = errorMessage || 'Invalid request format in item: ' + i;
break;
errorMessage = errorMessage || 'Invalid request format in item: ' + idx;
return false;
}

const payload = request.payload.requests[i].payload;
const payloadParts = internals.parsePayload(payloadRegex, payload);
const payloadParts = internals.parsePayload(req.payload);

payloads.push(payloadParts || []);
}
return true;
});

if (errorMessage === null) {
internals.process(request, requests, payloads, resultsData, reply);
}
else {
reply(Boom.badRequest(errorMessage));
if (errorMessage !== null) {
return reply(Boom.badRequest(errorMessage));
}

internals.process(request, requests, payloads, resultsData, reply);
},
notes: settings.notes,
description: settings.description,
Expand All @@ -106,28 +90,21 @@ internals.process = function (request, requests, payloads, resultsData, reply) {
const fnsParallel = [];
const fnsSerial = [];

const callBatch = function (pos, requestParts, payloadParts) {
requests.forEach((requestParts, idx) => {

return (callback) => {

internals.batch(request, resultsData, pos, requestParts, payloadParts, callback);
};
};
const payloadParts = payloads[idx];
if (internals.hasRefPart(requestParts) || payloadParts.length) {
return fnsSerial.push((callback) => {

let i = 0;
const il = requests.length;
internals.batch(request, resultsData, idx, requestParts, payloadParts, callback);
});
}

for ( ; i < il; ++i) {
const requestParts = requests[i];
const payloadParts = payloads[i];
fnsParallel.push((callback) => {

if (internals.hasRefPart(requestParts) || payloadParts.length) {
fnsSerial.push(callBatch(i, requestParts, payloadParts));
}
else {
fnsParallel.push(callBatch(i, requestParts));
}
}
internals.batch(request, resultsData, idx, requestParts, undefined, callback);
});
});

Async.series([
(callback) => {
Expand All @@ -152,62 +129,58 @@ internals.process = function (request, requests, payloads, resultsData, reply) {

internals.hasRefPart = function (parts) {

let i = 0;
const il = parts.length;
for ( ; i < il; ++i) {
if (parts[i].type === 'ref') {
return true;
}
}

return false;
return parts.some((part) => part.type === 'ref');
};

internals.buildPath = function (resultsData, pos, parts) {

let path = '';
let error = null;
let i = 0;
const il = parts.length;
let ref;
let value;
let part;
const partsLength = parts.length;

for ( ; i < il; ++i) {
for (let i = 0; i < partsLength; ++i) {
path += '/';
part = parts[i];

if (parts[i].type === 'ref') {
const ref = resultsData.resultsMap[parts[i].index];
if (part.type !== 'ref') {
path += part.value;
continue;
}

if (ref) {
const value = Hoek.reach(ref, parts[i].value);
ref = resultsData.resultsMap[part.index];

if (value !== null && value !== undefined) {
if (!ref) {
error = new Error('Missing reference response');
break;
}

if (/^[\w:]+$/.test(value)) {
path += value;
}
else {
error = new Error('Reference value includes illegal characters');
break;
}
}
else {
error = new Error('Reference not found');
break;
}
}
else {
error = new Error('Missing reference response');
break;
}
value = Hoek.reach(ref, part.value);

if (value === null || value === undefined) {
error = new Error('Reference not found');
break;
}
else {
path += parts[i].value;

if (!/^[\w:]+$/.test(value)) {
error = new Error('Reference value includes illegal characters');
break;
}

path += value;

}

return error ? error : path;
};

internals.parsePayload = function (re, obj) {
internals.payloadRegex = /^\$(\d+)(?:\.([^\s\$]*))?/;

internals.requestRegex = /(?:\/)(?:\$(\d)+\.)?([^\/\$]*)/g;

internals.parsePayload = function (obj) {

const payloadParts = [];

Expand All @@ -217,45 +190,52 @@ internals.parsePayload = function (re, obj) {

Traverse(obj).forEach(function (value) {

if (typeof value === 'string') {
const match = value.match(re);
if (match) {
payloadParts.push({
path: this.path,
resultIndex: match[1],
resultPath: match[2]
});
}
if (typeof value !== 'string') {
return;
}

const match = internals.payloadRegex.exec(value);

if (!match) {
return;
}

payloadParts.push({
path: this.path,
resultIndex: match[1],
resultPath: match[2]
});
});

return payloadParts;
};

internals.evalResults = function (results, index, path) {

let result = results[index];
const result = results[index];

if (path) {
result = Hoek.reach(result, path) || {};
if (!path) {
return result;
}

return result;
return Hoek.reach(result, path) || {};
};

internals.buildPayload = function (payload, resultsData, parts) {

let i = 0;
const il = parts.length;
for ( ; i < il; ++i) {
const partsLength = parts.length;
let result;
let part;
for ( let i = 0; i < partsLength; ++i) {

const result = internals.evalResults(resultsData.resultsMap, parts[i].resultIndex, parts[i].resultPath);
part = parts[i];
result = internals.evalResults(resultsData.resultsMap, part.resultIndex, part.resultPath);

if (parts[i].path.length) {
Traverse(payload).set(parts[i].path, result);
if (!part.path.length) {
payload = result;
}
else {
payload = result;
Traverse(payload).set(part.path, result);
}
}

Expand All @@ -272,25 +252,26 @@ internals.batch = function (batchRequest, resultsData, pos, requestParts, payloa
}

// Make request
batchRequest.payload.requests[pos].path = path;
const request = batchRequest.payload.requests[pos];

request.path = path;

if (payloadParts && payloadParts.length) {
const payload = internals.buildPayload(
batchRequest.payload.requests[pos].payload,

// Make payload
request.payload = internals.buildPayload(
request.payload,
resultsData,
payloadParts
);

// Make payload
batchRequest.payload.requests[pos].payload = payload;
}

internals.dispatch(batchRequest, batchRequest.payload.requests[pos], (data) => {
internals.dispatch(batchRequest, request, (data) => {

// If redirection
if (('' + data.statusCode).indexOf('3') === 0) {
batchRequest.payload.requests[pos].path = data.headers.location;
internals.dispatch(batchRequest, batchRequest.payload.requests[pos], (batchData) => {
request.path = data.headers.location;
internals.dispatch(batchRequest, request, (batchData) => {

const batchResult = batchData.result;

Expand All @@ -311,17 +292,19 @@ internals.batch = function (batchRequest, resultsData, pos, requestParts, payloa

internals.dispatch = function (batchRequest, request, callback) {

let path = request.path;
let path;

if (request.query) {
const urlObject = {
path = Url.format({
pathname: request.path,
query: request.query
};
path = Url.format(urlObject);
});
}
else {
path = request.path;
}

const body = (request.payload !== null && request.payload !== undefined ? JSON.stringify(request.payload) : null); // payload can be '' or 0
const body = (request.payload !== null && request.payload !== undefined ? JSON.stringify(request.payload) : null);
const injectOptions = {
url: path,
method: request.method,
Expand Down

0 comments on commit b463282

Please sign in to comment.