all files / keystone/lib/list/ getUniqueValue.js

8.33% Statements 2/24
0% Branches 0/10
0% Functions 0/4
9.09% Lines 2/22
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49                                                                                             
/**
 * Gets a unique value from a generator method by checking for documents with the same value.
 *
 * To avoid infinite loops when a unique value cannot be found, it will bail and pass back an
 * undefined value after 10 attemptes.
 *
 * WARNING: Because there will always be a small amount of time between checking for an
 * existing value and saving a document, race conditions can occur and it is possible that
 * another document has the 'unique' value assigned at the same time.
 *
 * Because of this, if true uniqueness is required, you should also create a unique index on
 * the database path, and handle duplicate errors thrown on save.
 *
 * @param {String} path to check for uniqueness
 * @param {Function} generator method to call to generate a new value
 * @param {Number} the maximum number of attempts (optional, defaults to 10)
 * @param {Function} callback(err, uniqueValue)
 */
function getUniqueValue (path, generator, limit, callback) {
	var model = this.model;
	var count = 0;
	var value;
	if (typeof limit === 'function') {
		callback = limit;
		limit = 10;
	}
	if (Array.isArray(generator)) {
		var fn = generator[0];
		var args = generator.slice(1);
		generator = function () {
			return fn.apply(this, args);
		};
	}
	var check = function () {
		if (count++ > 10) {
			return callback(undefined, undefined);
		}
		value = generator();
		model.count().where(path, value).exec(function (err, matches) {
			if (err) return callback(err);
			if (matches) return check();
			callback(undefined, value);
		});
	};
	check();
}
 
module.exports = getUniqueValue;