Skip to content

Commit

Permalink
Merge pull request feedhenry#25 from evanshortiss/sync-input-validations
Browse files Browse the repository at this point in the history
add fail fast behaviour for custom sync handlers
  • Loading branch information
evanshortiss authored Nov 7, 2016
2 parents 9f80fe7 + b91e06d commit 06cf547
Show file tree
Hide file tree
Showing 8 changed files with 332 additions and 213 deletions.
68 changes: 23 additions & 45 deletions lib/sync-DataSetModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@ var async = require('async');
var defaultDataHandler = require('./sync-datahandler');
var syncUtil = require('./sync-util');

/**
* Removes code duplication and adds safety by ensuring global handlers passed
* in are functions and not some other type.
* @param {String} handlerName The name of the handler, e.g "globalHandleRead"
* @param {Object} inst The instance to set it on if valid
* @return {Function}
*/
function generateGlobalSetter (handlerName, inst) {
return function _setGlobalHandler (handlerFn) {
syncUtil.ensureHandlerIsFunction(handlerName, handlerFn);
inst[handlerName] = handlerFn;
};
}

var self = {

globalListHandler: undefined,
Expand Down Expand Up @@ -485,42 +499,6 @@ var self = {
}
},

setGlobalListHandler: function (globalListHandler) {
self.globalListHandler = globalListHandler;
},

setGlobalCreateHandler: function (globalCreateHandler) {
self.globalCreateHandler = globalCreateHandler;
},

setGlobalReadHandler: function (globalReadHandler) {
self.globalReadHandler = globalReadHandler;
},

setGlobalUpdateHandler: function (globalUpdateHandler) {
self.globalUpdateHandler = globalUpdateHandler;
},

setGlobalDeleteHandler: function (globalDeleteHandler) {
self.globalDeleteHandler = globalDeleteHandler;
},

setGlobalCollisionHandler: function (globalCollisionHandler) {
self.globalCollisionHandler = globalCollisionHandler;
},

setGlobalCollisionLister: function (globalCollisionLister) {
self.globalCollisionLister = globalCollisionLister;
},

setGlobalCollisionRemover: function (globalCollisionRemover) {
self.globalCollisionRemover = globalCollisionRemover;
},

setGlobalRequestInterceptor: function (globalRequestInterceptor) {
self.globalRequestInterceptor = globalRequestInterceptor;
},

setDefaultHandlers: function () {
self.globalListHandler = defaultDataHandler.doList;
self.globalCreateHandler = defaultDataHandler.doCreate;
Expand Down Expand Up @@ -595,15 +573,15 @@ var init = function () {

module.exports = {
forceSyncList: self.forceSyncList,
setGlobalListHandler: self.setGlobalListHandler,
setGlobalCreateHandler: self.setGlobalCreateHandler,
setGlobalReadHandler: self.setGlobalReadHandler,
setGlobalUpdateHandler: self.setGlobalUpdateHandler,
setGlobalDeleteHandler: self.setGlobalDeleteHandler,
setGlobalCollisionHandler: self.setGlobalCollisionHandler,
setGlobalCollisionLister: self.setGlobalCollisionLister,
setGlobalCollisionRemover: self.setGlobalCollisionRemover,
setGlobalRequestInterceptor: self.setGlobalRequestInterceptor,
setGlobalListHandler: generateGlobalSetter('globalListHandler', self),
setGlobalCreateHandler: generateGlobalSetter('globalCreateHandler', self),
setGlobalReadHandler: generateGlobalSetter('globalReadHandler', self),
setGlobalUpdateHandler: generateGlobalSetter('globalUpdateHandler', self),
setGlobalDeleteHandler: generateGlobalSetter('globalDeleteHandler', self),
setGlobalCollisionHandler: generateGlobalSetter('globalCollisionHandler', self),
setGlobalCollisionLister: generateGlobalSetter('globalCollisionLister', self),
setGlobalCollisionRemover: generateGlobalSetter('globalCollisionRemover', self),
setGlobalRequestInterceptor: generateGlobalSetter('globalRequestInterceptor', self),
doListHandler: self.doListHandler,
doCreateHandler: self.doCreateHandler,
doReadHandler: self.doReadHandler,
Expand Down
233 changes: 68 additions & 165 deletions lib/sync-srv.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,54 @@ module.exports = function (cfg) {
var syncInited = false;

var sync = function () {


/**
* Generic setter that can be used to override a default sync handler.
* Ensures passed in handler is a function and throws an AssertionError if not
*
* @param {String} target The handler to override
* @return {Function}
*/
function generateSetHandlerFn (target) {
return function _doSetHandler (dataset_id, fn) {
syncUtil.ensureHandlerIsFunction(target, fn);

DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset[target] = fn;
}
});
};
}


/**
* Each handler override that is supported needs a setter function, this
* generates them so they can be attached to the sync instance.
*
* For example this will bind and $fh.sync.handleList function, which allows
* one to set a custom "listHandler"
*
* @return {Object}
*/
function bindHandlerSetters (instance) {
var handlerMap = {
handleList: 'listHandler',
handleCreate: 'createHandler',
handleRead: 'readHandler',
handleUpdate: 'updateHandler',
handleDelete: 'deleteHandler',
handleCollision: 'collisionHandler',
listCollisions: 'collisionLister',
removeCollision: 'collisionRemover',
interceptRequest: 'requestInterceptor'
};

Object.keys(handlerMap).forEach(function (key) {
instance[key] = generateSetHandlerFn(handlerMap[key]);
});
}

var globalInit = function () {
if (!syncInited) {
syncInited = true;
Expand All @@ -27,180 +74,36 @@ var sync = function () {
}
}

var init = function (dataset_id, options, cb) {
initDataset(dataset_id, options, cb);
};

var invoke = function (dataset_id, params, callback) {
return doInvoke(dataset_id, params, callback);
};

var stop = function (dataset_id, callback) {
return stopDatasetSync(dataset_id, callback);
};

var stopAll = function (callback) {
return stopAllDatasetSync(callback);
};

var toJSON = function (dataset_id, returnData, cb) {
return DataSetModel.toJSON(dataset_id, returnData, cb);
};

var globalHandleList = function (fn) {
DataSetModel.setGlobalListHandler(fn);
};

var globalHandleCreate = function (fn) {
DataSetModel.setGlobalCreateHandler(fn);
};

var globalHandleRead = function (fn) {
DataSetModel.setGlobalReadHandler(fn);
};

var globalHandleUpdate = function (fn) {
DataSetModel.setGlobalUpdateHandler(fn);
};

var globalHandleDelete = function (fn) {
DataSetModel.setGlobalDeleteHandler(fn);
};

var globalHandleCollision = function (fn) {
DataSetModel.setGlobalCollisionHandler(fn);
};

var globalListCollisions = function (fn) {
DataSetModel.setGlobalCollisionLister(fn);
};

var globalRemoveCollision = function (fn) {
DataSetModel.setGlobalCollisionRemover(fn);
};

var globalInterceptRequest = function (fn) {
DataSetModel.setGlobalRequestInterceptor(fn);
};

var handleList = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.listHandler = fn;
}
});
};

var handleCreate = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.createHandler = fn;
}
});
};

var handleRead = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.readHandler = fn;
}
});
};

var handleUpdate = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.updateHandler = fn;
}
});
};

var handleDelete = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.deleteHandler = fn;
}
});
};

var handleCollision = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.collisionHandler = fn;
}
});
};

var listCollisions = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.collisionLister = fn;
}
});
};

var removeCollision = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.collisionRemover = fn;
}
});
};
globalInit();

var interceptRequest = function (dataset_id, fn) {
DataSetModel.getDataset(dataset_id, function (err, dataset) {
if (!err) {
dataset.requestInterceptor = fn;
}
});
var instance = {
init: DataSetModel.createDataset.bind(null),
invoke: doInvoke.bind(null),
stop: DataSetModel.stopDatasetSync.bind(null),
stopAll: DataSetModel.stopAllDatasetSync.bind(null),
toJSON: DataSetModel.toJSON.bind(null),
setLogLevel: doSetLogLevel,
globalHandleList: DataSetModel.setGlobalListHandler.bind(null),
globalHandleCreate: DataSetModel.setGlobalCreateHandler.bind(null),
globalHandleRead: DataSetModel.setGlobalReadHandler.bind(null),
globalHandleUpdate: DataSetModel.setGlobalUpdateHandler.bind(null),
globalHandleDelete: DataSetModel.setGlobalDeleteHandler.bind(null),
globalHandleCollision: DataSetModel.setGlobalCollisionHandler.bind(null),
globalListCollisions: DataSetModel.setGlobalCollisionLister.bind(null),
globalRemoveCollision: DataSetModel.setGlobalCollisionRemover.bind(null),
globalInterceptRequest: DataSetModel.setGlobalRequestInterceptor.bind(null)
};

globalInit();
// Make sure to bind custom handler setters
bindHandlerSetters(instance);

return {
init: init,
invoke: invoke,
stop: stop,
stopAll: stopAll,
toJSON: toJSON,
setLogLevel: doSetLogLevel,
globalHandleList: globalHandleList,
globalHandleCreate: globalHandleCreate,
globalHandleRead: globalHandleRead,
globalHandleUpdate: globalHandleUpdate,
globalHandleDelete: globalHandleDelete,
globalHandleCollision: globalHandleCollision,
globalListCollisions: globalListCollisions,
globalRemoveCollision: globalRemoveCollision,
globalInterceptRequest: globalInterceptRequest,
handleList: handleList,
handleCreate: handleCreate,
handleRead: handleRead,
handleUpdate: handleUpdate,
handleDelete: handleDelete,
handleCollision: handleCollision,
listCollisions: listCollisions,
removeCollision: removeCollision,
interceptRequest: interceptRequest
}
return instance;
}

/* ======================================================= */
/* ================== PRIVATE FUNCTIONS ================== */
/* ======================================================= */

function initDataset(dataset_id, options, cb) {
DataSetModel.createDataset(dataset_id, options, cb);
}

function stopDatasetSync(dataset_id, cb) {
DataSetModel.stopDatasetSync(dataset_id, cb);
}

function stopAllDatasetSync(cb) {
DataSetModel.stopAllDatasetSync(cb);
}

/* jshint ignore:start */
function toJSON(dataset_id, returnData, cb) {
DataSetModel.toJSON(dataset_id, returnData, cb);
Expand Down
9 changes: 9 additions & 0 deletions lib/sync-util.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var crypto = require('crypto');
var winston = require('winston');
var moment = require('moment');
var assert = require('assert');

var SYNC_LOGGER = 'SYNC';
var loggers = {};
Expand Down Expand Up @@ -81,6 +82,14 @@ var getCuid = function (params) {
return cuid;
}

exports.ensureHandlerIsFunction = function (target, fn) {
assert.equal(
typeof fn,
'function',
'sync handler (' + target + ') must be a function'
);
};

module.exports.generateHash = generateHash;
module.exports.sortObject = sortObject;
module.exports.sortedStringify = sortedStringify;
Expand Down
4 changes: 2 additions & 2 deletions test/fixtures/syncHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ exports.doRead = function(dataset_id, uid, cb) {
return cb(null, {});
};

exports.listCollissions = function(dataset_id, uid, cb) {
exports.listCollisions = function(dataset_id, uid, cb) {
console.log("listCollisions : ", dataset_id, " :: ", uid);
return cb(null, {});
};
Expand All @@ -36,4 +36,4 @@ exports.doCollision = function(dataset_id, hash, uid, pre, post) {

exports.removeCollision = function(dataset_id, hash, cb) {
return cb(null, {});
}
}
2 changes: 1 addition & 1 deletion test/test_sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ module.exports = {
ditchMock.done();
finish();
});

}
};
Loading

0 comments on commit 06cf547

Please sign in to comment.