Commit b8039434 authored by Sven Franck's avatar Sven Franck

work-in-progress replicate master-slave storage

parent 074b9ddc
...@@ -1073,6 +1073,87 @@ ...@@ -1073,6 +1073,87 @@
storage.write(obj); storage.write(obj);
}, },
/**
* Create an installation = new service object
* @method install
* @param {object} obj Action Object
**/
"install": function (obj) {
// force new portal type and POST (create new record)
obj.gadget.state.force_type = "Service";
obj.gadget.state.create_new = true;
storage.add(obj);
},
/**
* Destroy an installation = service object
* @method destroy
* @param {object} obj Action Object
**/
"destroy": function (obj) {
storage.remove(obj);
},
/**
* Start a software instance
* @method start_instance
* @param {object} obj Action Object
**/
"update_ticket": function (obj) {
var element = obj.element, formData, valid, replace, property, value, id,
decode, store;
id = obj.state.fragment_list[1];
formData = new FormData();
store = app.storage_dict;
valid = storage.validate(obj.gadget);
decode = /^[^\/]*%2[^\/]*$/.test(id);
if (valid === undefined) {
util.loader("", "validation_dict.general", "ban-circle");
// form is valid and not "spam"
} else {
replace = obj.gadget.id + "_";
for (property in valid) {
if (valid.hasOwnProperty(property)) {
value = valid[property];
// prepare to store
// TODO: add id to captcha fields missing it...
if (property !== "undefined") {
if (property !== "identifier") {
formData.append(property.replace(replace, ""), value);
}
}
}
}
util.loader("", "status_dict.updating");
store.items.get({"_id": window.decodeURIComponent(obj.state.fragment_list[1])},{"_view": "web_view"})
.then(function(response) {
return jIO.util.ajax({
"url": util.parse(response).data._actions.update.href,
"type": "POST",
"data": formData,
"xhrFields": {
"withCredentials": true
}
});
})
.then(function (answer) {
util.loader("", "status_dict.success", "check");
$.mobile.changePage("#services");
})
.fail(function(error) {
util.error(error);
if (util.parse(error.target).responseText === "" && id && obj.state.callback) {
$.mobile.changePage(obj.state.callback.replace("__id__", decode ? id : window.encodeURIComponent(id)));
}
});
}
},
/** /**
* Start a software instance * Start a software instance
* @method start_instance * @method start_instance
...@@ -1326,87 +1407,6 @@ ...@@ -1326,87 +1407,6 @@
}); });
}, },
/**
* Create an installation = new service object
* @method install
* @param {object} obj Action Object
**/
"install": function (obj) {
// force new portal type and POST (create new record)
obj.gadget.state.force_type = "Service";
obj.gadget.state.create_new = true;
storage.add(obj);
},
/**
* Destroy an installation = service object
* @method destroy
* @param {object} obj Action Object
**/
"destroy": function (obj) {
storage.remove(obj);
},
/**
* Start a software instance
* @method start_instance
* @param {object} obj Action Object
**/
"update_ticket": function (obj) {
var element = obj.element, formData, valid, replace, property, value, id,
decode, store;
id = obj.state.fragment_list[1];
formData = new FormData();
store = app.storage_dict;
valid = storage.validate(obj.gadget);
decode = /^[^\/]*%2[^\/]*$/.test(id);
if (valid === undefined) {
util.loader("", "validation_dict.general", "ban-circle");
// form is valid and not "spam"
} else {
replace = obj.gadget.id + "_";
for (property in valid) {
if (valid.hasOwnProperty(property)) {
value = valid[property];
// prepare to store
// TODO: add id to captcha fields missing it...
if (property !== "undefined") {
if (property !== "identifier") {
formData.append(property.replace(replace, ""), value);
}
}
}
}
util.loader("", "status_dict.updating");
store.items.get({"_id": window.decodeURIComponent(obj.state.fragment_list[1])},{"_view": "web_view"})
.then(function(response) {
return jIO.util.ajax({
"url": util.parse(response).data._actions.update.href,
"type": "POST",
"data": formData,
"xhrFields": {
"withCredentials": true
}
});
})
.then(function (answer) {
util.loader("", "status_dict.success", "check");
$.mobile.changePage("#services");
})
.fail(function(error) {
util.error(error);
if (util.parse(error.target).responseText === "" && id && obj.state.callback) {
$.mobile.changePage(obj.state.callback.replace("__id__", decode ? id : window.encodeURIComponent(id)));
}
});
}
},
// ============================================================== // ==============================================================
/** /**
...@@ -5540,7 +5540,7 @@ ...@@ -5540,7 +5540,7 @@
data._id = form.identifier.value; data._id = form.identifier.value;
} else { } else {
config = { config = {
"call": obj.state.url_pointer[obj.element.getAttribute("data-action")] "action": obj.state.url_pointer[obj.element.getAttribute("data-action")]
}; };
} }
...@@ -5548,14 +5548,18 @@ ...@@ -5548,14 +5548,18 @@
app.storage_dict.items[method || "post"](data, config) app.storage_dict.items[method || "post"](data, config)
) )
.then(function (response) { .then(function (response) {
util.loader("", "status_dict.saved", "check"); if (response.status === 201) {
if (obj.state.callback) { util.loader("", "status_dict.saved", "check");
answer = util.parse(response); if (obj.state.callback) {
id = answer.id; answer = util.parse(response);
decode = /^[^\/]*%2[^\/]*$/.test(id); id = answer.id;
goto = decode ? id : window.encodeURIComponent(id); decode = /^[^\/]*%2[^\/]*$/.test(id);
goto = decode ? id : window.encodeURIComponent(id);
$.mobile.changePage(obj.state.callback.replace("__id__", goto)); $.mobile.changePage(obj.state.callback.replace("__id__", goto));
}
} else {
util.loader("", "status_dict.error", "ban-circle");
} }
}).fail(util.error); }).fail(util.error);
}; };
......
...@@ -23,38 +23,48 @@ ...@@ -23,38 +23,48 @@
this._url = spec.url; this._url = spec.url;
} }
ERP5Storage.prototype._getSiteDocument = function () { ERP5Storage.prototype._getPrivates = function (site_hal, param, options) {
var fetch, item = (param || {})._id || (site_hal._links.me || {}).href;
if (!item) {
return command.error(401);
}
fetch = new URI(item);
return this._getSiteDocument(
site_hal._links.traverse.href,
{"relative_url": fetch.segment(2) || item, "view": options._view}
);
};
ERP5Storage.prototype._getSiteDocument = function (traverse, expando) {
var url = UriTemplate.parse(traverse || "").expand(expando || {});
console.log(url);
return jIO.util.ajax({ return jIO.util.ajax({
"type": "GET", "type": "GET",
"url": this._url, "url": url || this._url,
"xhrFields": { "xhrFields": {
withCredentials: true "withCredentials": true
} }
}).then(function (response) { }).then(function (response) {
return JSON.parse(response.target.responseText); var result = JSON.parse(response.target.responseText);
// result._id = param._id;
return result;
}); });
}; };
ERP5Storage.prototype._get = function (param, options) { ERP5Storage.prototype._get = function (param, options) {
return this._getSiteDocument() var that = this;
.then(function (site_hal) { return that._getSiteDocument()
return jIO.util.ajax({ .then(function (site_hal) {
"type": "GET", return that._getPrivates(site_hal, param, options);
"url": UriTemplate.parse(site_hal._links.traverse.href) })
.expand({ .then(function (response) {
relative_url: param._id, console.log("GET, response")
view: options._view console.log(response)
}), var result = JSON.parse(response.target.responseText);
"xhrFields": { result._id = param._id;
withCredentials: true return result;
} });
});
})
.then(function (response) {
var result = JSON.parse(response.target.responseText);
result._id = param._id;
return result;
});
}; };
ERP5Storage.prototype.get = function (command, param, options) { ERP5Storage.prototype.get = function (command, param, options) {
...@@ -74,11 +84,15 @@ ...@@ -74,11 +84,15 @@
}; };
ERP5Storage.prototype.post = function (command, metadata, options) { ERP5Storage.prototype.post = function (command, metadata, options) {
return this._getSiteDocument() var that = this;
return that._getSiteDocument()
.then(function (site_hal) { .then(function (site_hal) {
var post_action = site_hal._actions.add, return that._getPrivates(site_hal, undefined, options);
data = new FormData(), })
key; .then(function(opts) {
var key, custom_action = opts._actions[options.action],
post_action = custom_action || site_hal._actions.add,
data = new FormData();
for (key in metadata) { for (key in metadata) {
if (metadata.hasOwnProperty(key)) { if (metadata.hasOwnProperty(key)) {
...@@ -86,17 +100,18 @@ ...@@ -86,17 +100,18 @@
data.append(key, metadata[key]); data.append(key, metadata[key]);
} }
} }
return jIO.util.ajax({ return jIO.util.ajax({
"type": post_action.method, "type": post_action.method,
"url": post_action.href, "url": post_action.href,
"data": data, "data": data,
"xhrFields": { "xhrFields": {
withCredentials: true "withCredentials": true
} }
}); });
}).then(function (doc) { }).then(function (doc) {
// XXX Really depend on server response... // XXX Really depend on server response...
var uri = new URI(doc.target.getResponseHeader("Location")); var uri = new URI(doc.target.getResponseHeader("X-Location"));
command.success({"id": uri.segment(2)}); command.success({"id": uri.segment(2)});
}).fail(function (error) { }).fail(function (error) {
console.error(error); console.error(error);
......
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
"xhrFields": { "xhrFields": {
"withCredentials": true "withCredentials": true
} }
}) })z
}) })
.then(function (opts) { .then(function (opts) {
var doc_hal, custom_action, post_action, data, key; var doc_hal, custom_action, post_action, data, key;
......
...@@ -177,13 +177,16 @@ ...@@ -177,13 +177,16 @@
* last(promise_list): Promise * last(promise_list): Promise
* *
* @param {Array} promise_list An array of promises * @param {Array} promise_list An array of promises
* @param {Integer} master The "promise" with id authority
* @return {Promise} A new promise * @return {Promise} A new promise
*/ */
function last(promise_list) { function last(promise_list, master) {
var length = promise_list.length; var length = promise_list.length;
promise_list = promise_list.slice(); promise_list = promise_list.slice();
return new Promise(function (resolve, reject, notify) { return new Promise(function (resolve, reject, notify) {
var index, last_answer, count = 0, error_count = 0; var index, last_answer, count = 0, error_count = 0;
function resolver() { function resolver() {
return function (answer) { return function (answer) {
count += 1; count += 1;
...@@ -213,8 +216,14 @@ ...@@ -213,8 +216,14 @@
}); });
}; };
} }
for (index = 0; index < length; index += 1) {
promise_list[index].then(resolver(), rejecter(), notifier(index)); if (typeof master === "number") {
length = 1;
promise_list[master].then(resolver(), rejecter(), notifier(master));
} else {
for (index = 0; index < length; index += 1) {
promise_list[index].then(resolver(), rejecter(), notifier(index));
}
} }
}, function () { }, function () {
var index; var index;
...@@ -309,18 +318,60 @@ ...@@ -309,18 +318,60 @@
"storage_list is not of type array"); "storage_list is not of type array");
} }
this._storage_list = spec.storage_list; this._storage_list = spec.storage_list;
this._master = spec.master;
} }
ReplicateStorage.prototype.post = function (command, metadata, option) { ReplicateStorage.prototype.post = 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] = success( promise_list = [],
command.storage(this._storage_list[index]).post(metadata, option) priority_list = [],
length = storages.length,
master = this._master;
// first run priority storage
if (master !== undefined) {
priority_list[0] = success(
command.storage(storages[master]).post(metadata, option)
); );
} else {
for (index = 0; index < length; index += 1) {
promise_list[index] = success(
command.storage(storages[index]).post(metadata, option)
);
}
} }
sequence([function () {
return last(promise_list); sequence([
}, [command.success, command.error]]); function () {
if (master !== undefined) {
return last(priority_list, master);
}
return {};
},
function (response) {
var method, subindex = 0;
// this is the id issued by the master storage
if (response.id) {
metadata._id = response.id;
method = "put";
} else {
// TODO: error/offline handling
}
for (index = 0; index < length; index += 1) {
if (index !== master) {
promise_list[subindex] = success(
command.storage(storages[index])
[method || "post"](metadata, option)
);
subindex += 1;
}
}
return last(promise_list);
},
[command.success, command.error]
]);
}; };
ReplicateStorage.prototype.put = function (command, metadata, option) { ReplicateStorage.prototype.put = function (command, metadata, 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