Commit ae26852d authored by Sven Franck's avatar Sven Franck

temporary commit on replicatestorage with master/slave

parent 7bfedd00
...@@ -45,11 +45,12 @@ ...@@ -45,11 +45,12 @@
addStorageFunction = require('jio').addStorage; addStorageFunction = require('jio').addStorage;
/** /**
* Make a clean clone of an object with clean referring to removal of all * Make a clone of an object WITHOUT _xxx (except _id). This is what is
* flags indicating missing or non-coherent elements. * compared when compared when checking answers from multiple storages
* @method cleanClone
* @param {Object} obj to clone * @param {Object} obj to clone
* @return {Object} clones object * @return {Object} clones object
*/ **/
function cleanClone (obj) { function cleanClone (obj) {
var prop, r = {}; var prop, r = {};
...@@ -60,16 +61,16 @@ ...@@ -60,16 +61,16 @@
} }
} }
} }
return r; return r;
}; };
/** /**
* Generate a checksum from a passed string to compare the response returned * Generate a checksum from a passed string to compare the response returned
* by multiple storages for the same requests. * by multiple storages for the same requests.
* @method checksum
* @param {Object} obj to generate a checksum for * @param {Object} obj to generate a checksum for
* @return {Integer} checksum * @return {Integer} checksum
*/ **/
function checksum (obj) { function checksum (obj) {
var r, i, str = JSON.stringify(obj); var r, i, str = JSON.stringify(obj);
...@@ -129,45 +130,6 @@ ...@@ -129,45 +130,6 @@
}); });
} }
// /**
// * Awaits for an answer from one promise only. Promises are cancelled only
// * by calling `first(promise_list).cancel()`.
// *
// * first(promise_list): Promise
// *
// * @param {Array} promise_list An array of promises
// * @return {Promise} A new promise
// */
// function first(promise_list) {
// var length = promise_list.length;
// promise_list = promise_list.slice();
// return new Promise(function (resolve, reject, notify) {
// var index, count = 0;
// function rejecter(answer) {
// count += 1;
// if (count === length) {
// return reject(answer);
// }
// }
// function notifier(index) {
// return function (notification) {
// notify({
// "index": index,
// "value": notification
// });
// };
// }
// for (index = 0; index < length; index += 1) {
// promise_list[index].then(resolve, rejecter, notifier(index));
// }
// }, function () {
// var index;
// for (index = 0; index < length; index += 1) {
// promise_list[index].cancel();
// }
// });
// }
/** /**
* Responds with the last resolved promise answer recieved. If all promises * Responds with the last resolved promise answer recieved. If all promises
* are rejected, it returns the latest rejected promise answer * are rejected, it returns the latest rejected promise answer
...@@ -178,9 +140,11 @@ ...@@ -178,9 +140,11 @@
* *
* @param {Array} promise_list An array of promises * @param {Array} promise_list An array of promises
* @param {Integer} master The "promise" with id authority * @param {Integer} master The "promise" with id authority
* @param {Object} temp Any temporary data created by master
* @return {Promise} A new promise * @return {Promise} A new promise
*/ */
function last(promise_list, master) { // NOTE: added master parameter for master-slave storage
function last(promise_list, master, temp) {
var length = promise_list.length; var length = promise_list.length;
promise_list = promise_list.slice(); promise_list = promise_list.slice();
...@@ -191,6 +155,9 @@ ...@@ -191,6 +155,9 @@
return function (answer) { return function (answer) {
count += 1; count += 1;
if (count === length) { if (count === length) {
if (temp) {
answer._temp = temp;
}
return resolve(answer); return resolve(answer);
} }
last_answer = answer; last_answer = answer;
...@@ -204,6 +171,9 @@ ...@@ -204,6 +171,9 @@
} }
count += 1; count += 1;
if (count === length) { if (count === length) {
if (temp) {
answer._temp = temp;
}
return resolve(last_answer); return resolve(last_answer);
} }
}; };
...@@ -234,19 +204,12 @@ ...@@ -234,19 +204,12 @@
} }
/** /**
* Test a GET response across multiple storages. Returns first valid document * Test responses of a GET request for coherence (will set _conflict)
* together with the following parameters: * and missing (will set _missing) on the returned document
* * @method checkAndReturn
* _missing = true > when a storage returns a 404 for this document * @param {Object} promise_list List of responses received
* _conflict_list = [] > all docs in conflict (including "self")
*
* Promises are cancelled only by calling
*
* `checkAndReturn(promise_list).cancel()`
*
* @param {Array} promise_list An array of promises
* @return {Promise} A new promise * @return {Promise} A new promise
*/ **/
function checkAndReturn(promise_list) { function checkAndReturn(promise_list) {
var length = promise_list.length; var length = promise_list.length;
...@@ -318,7 +281,8 @@ ...@@ -318,7 +281,8 @@
} }
this._storage_list = spec.storage_list; this._storage_list = spec.storage_list;
this._master = spec.master; this._master = spec.master;
} };
ReplicateStorage.prototype.post = function (command, metadata, option) { ReplicateStorage.prototype.post = function (command, metadata, option) {
var index, subindex, var index, subindex,
...@@ -341,16 +305,15 @@ ...@@ -341,16 +305,15 @@
} }
} }
// first master, then slave
sequence([ sequence([
function () { function () {
// master storage
if (master !== undefined) { if (master !== undefined) {
return last(priority_list, master); return last(priority_list, master);
} }
return {}; return {};
}, },
function (response) { function (response) {
// slave storages
var method, subindex = 0; var method, subindex = 0;
if (response.id) { if (response.id) {
metadata._id = response.id; metadata._id = response.id;
...@@ -375,14 +338,52 @@ ...@@ -375,14 +338,52 @@
}; };
ReplicateStorage.prototype.put = function (command, metadata, option) { ReplicateStorage.prototype.put = function (command, metadata, option) {
var promise_list = [], index, length = this._storage_list.length; var index, subindex,
for (index = 0; index < length; index += 1) { storages = this._storage_list,
promise_list[index] = promise_list = [],
command.storage(this._storage_list[index]).put(metadata, option); priority_list = [],
length = storages.length,
master = this._master;
// setup master storage or all
if (master !== undefined) {
priority_list[0] = success(
command.storage(storages[master]).put(metadata, option)
);
} else {
for (index = 0; index < length; index += 1) {
promise_list[index] = success(
command.storage(storages[index]).put(metadata, option)
);
}
} }
sequence([function () {
return last(promise_list); // run master, then slave
}, [command.success, command.error]]); sequence([
function () {
return last(priority_list, master);
},
function (response) {
var subindex;
switch (true) {
case response.status >= 500: command.error(response); break;
// HACK: why does 204 return status code 0 on promises?
case response.status === 0:
default:
for (index = 0, subindex = 0; index < length; index += 1) {
if (index !== master) {
promise_list[subindex] = success(
command.storage(storages[index]).put(metadata, option)
);
subindex += 1;
}
}
return last(promise_list, undefined, response._temp);
}
},
[command.success, command.error]
]);
}; };
ReplicateStorage.prototype.putAttachment = function (command, param, option) { ReplicateStorage.prototype.putAttachment = function (command, param, option) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment