Commit eae4943a authored by Alain Takoudjou's avatar Alain Takoudjou

replicated opml storage: improvements, update scenario test

parent a5515a0a
......@@ -10,6 +10,7 @@
<link rel="stylesheet" href="../node_modules/grunt-contrib-qunit/test/libs/qunit.css" type="text/css" media="screen"/>
<script src="../node_modules/grunt-contrib-qunit/test/libs/qunit.js" type="text/javascript"></script>
<script src="../node_modules/sinon/pkg/sinon.js" type="text/javascript"></script>
<script src="scenario_monitor.js"></script>
</head>
......
/*global Blob, Rusha, console*/
/*global Blob, Rusha, sinon, console*/
/*jslint nomen: true, maxlen: 80*/
(function (QUnit, jIO, Blob, Rusha, console) {
(function (QUnit, jIO, Blob, Rusha, sinon, console) {
"use strict";
var test = QUnit.test,
// equal = QUnit.equal,
......@@ -29,15 +29,6 @@
type: "rss",
url: "http://example.com/rss.xml"
});
this._sub_storage = jIO.createJIO({
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "memory"
}
}
});
this._options = spec.options;
resetCount(spec.options.count);
}
......@@ -49,16 +40,7 @@
function WEBMockStorage(spec) {
this._web_storage = jIO.createJIO({
type: "webhttp",
url: "http://example.com/private/"
});
this._sub_storage = jIO.createJIO({
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "memory"
}
}
url: "http://example.com/"
});
this._options = spec.options;
resetCount(spec.options.count);
......@@ -73,15 +55,6 @@
type: "opml",
url: "http://example.com/opml.xml"
});
this._sub_storage = jIO.createJIO({
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "memory"
}
}
});
this._options = spec.options;
resetCount(spec.options.count);
}
......@@ -96,21 +69,21 @@
if (this._options.mock.hasOwnProperty(name)) {
return this._options.mock[name].apply(this, arguments);
}
return this._sub_storage[name].apply(this._sub_storage, arguments);
return this._web_storage[name].apply(this._web_storage, arguments);
};
RSSMockStorage.prototype[name] = function () {
this._options.count[name] += 1;
if (this._options.mock.hasOwnProperty(name)) {
return this._options.mock[name].apply(this, arguments);
}
return this._sub_storage[name].apply(this._sub_storage, arguments);
return this._rss_storage[name].apply(this._rss_storage, arguments);
};
OPMLMockStorage.prototype[name] = function () {
this._options.count[name] += 1;
if (this._options.mock.hasOwnProperty(name)) {
return this._options.mock[name].apply(this, arguments);
}
return this._sub_storage[name].apply(this._sub_storage, arguments);
return this._opml_storage[name].apply(this._opml_storage, arguments);
};
}
......@@ -128,9 +101,6 @@
function generateHash(str) {
return rusha.digestFromString(str);
}
function putFullDoc(storage, id, doc) {
return storage.put(id, doc);
}
function equalStorage(storage, doc_tuple_list) {
return storage.allDocs({include_docs: true})
......@@ -166,59 +136,39 @@
deepEqual(mock_count, expected_count, 'Expected method call count');
}
function getOpmlElement(doc, doc_id, url) {
var element,
id,
parent_id;
parent_id = generateHash(url);
id = generateHash(parent_id + doc_id);
element = {
name: doc_id,
opml_title: doc.opml_title,
parent_id: parent_id,
reference: id,
creation_date: doc.created_date,
title: doc.title,
type: "opml-item",
url: url
};
return {
id: id,
doc: element
};
}
function getSubOpmlElement(doc, doc_id, opml_doc, url, type) {
var id = generateHash(opml_doc.reference + url + doc_id);
return {
id: id,
doc: {
name: doc_id,
opml_title: opml_doc.opml_title,
parent_title: opml_doc.title,
parent_id: opml_doc.reference,
reference: id,
title: doc.title,
type: doc.type || type + "-item",
url: url,
status: doc.status,
creation_date: doc.date
}
};
}
///////////////////////////////////////////////////////
// Module
///////////////////////////////////////////////////////
module("scenario_monitor", {
setup: function () {
this.server = sinon.fakeServer.create();
this.server.autoRespond = true;
this.server.autoRespondAfter = 5;
this.rss_mock_options = {
mock: {
remove: function () {
throw new Error('remove not supported');
},
removehas_include_docs: function () {
removeAttachment: function () {
throw new Error('removeAttachment not supported');
},
allAttachments: function () {
return {data: null};
},
putAttachment: function () {
throw new Error('putAttachment not supported');
}
},
count: {}
};
this.opml_mock_options = {
mock: {
remove: function () {
throw new Error('remove not supported');
},
removeAttachment: function () {
throw new Error('removeAttachment not supported');
},
allAttachments: function () {
......@@ -230,9 +180,6 @@
},
count: {}
};
this.opml_mock_options = JSON.parse(
JSON.stringify(this.rss_mock_options)
);
this.web_mock_options = {
mock: {
remove: function () {
......@@ -263,7 +210,7 @@
},
{
type: "webmock",
url: "http://example.com/data/",
url: "http://example.com/",
has_include_docs: true,
options: this.web_mock_options
}
......@@ -285,6 +232,66 @@
}
}
});
this.server.respondWith("GET", "http://example.com/opml.xml", [200,
{ "Content-Type": "text/xml" },
'<?xml version="1.0" encoding="ISO-8859-1"?>' +
'<opml version="1.0">' +
'<head>' +
'<title>opml foo</title>' +
'<dateCreated>Thu, 12 Sep 2003 23:35:52 GMT</dateCreated>' +
'<dateModified>Fri, 12 Sep 2003 23:45:37 GMT</dateModified>' +
'</head>' +
'<body>' +
'<outline text="OPML Item List">' +
'<outline text="instance foo" type="link" url="http://example.com/' +
'rss.xml" dateCreated="Thu, 12 Sep 2003 23:35:52 GMT" ' +
'htmlUrl="http://example.com/" title="opml item foo" />' +
'</outline>' +
'</body>' +
'</opml>'
]);
this.server.respondWith("GET", "http://example.com/rss.xml", [200,
{ "Content-Type": "text/xml" },
'<?xml version="1.0" encoding="UTF-8" ?>' +
'<rss version="2.0">' +
'<channel>' +
'<title>instance foo</title>' +
'<description>This is an example of an RSS feed</description>' +
'<link>http://www.domain.com/link.htm</link>' +
'<lastBuildDate>Mon, 28 Aug 2006 11:12:55 -0400 </lastBuildDate>' +
'<pubDate>Tue, 29 Aug 2006 09:00:00 -0400</pubDate>' +
'<item>' +
'<title>Item Example</title>' +
'<category>ERROR</category>' +
'<description>This is an example of an Item</description>' +
'<link>http://www.domain.com/link.htm</link>' +
'<guid isPermaLink="false">1102345</guid>' +
'<pubDate>Tue, 29 Aug 2006 09:00:00 -0400</pubDate>' +
'</item>' +
'</channel>' +
'</rss>'
]);
this.server.respondWith("GET", "http://example.com/_document_list", [200,
{ "Content-Type": "text/plain" },
'monitor.status'
]);
this.server.respondWith(
"GET",
"http://example.com/monitor.status.json",
[200,
{ "Content-Type": "application/json" },
'{"title": "document fooo", "status": "ERROR",' +
'"date": "Tue, 29 Aug 2006 09:00:00 -0400",' +
'"type": "global", "foo_p": "fooo parameter",' +
'"bar_p": "bar parameter", "total_error": 12345}']
);
},
teardown: function () {
this.server.restore();
delete this.server;
}
});
......@@ -297,6 +304,9 @@
var test = this;
test.opml_mock_options.mock.buildQuery = function () {
return [];
};
this.jio.repair()
.then(function () {
return RSVP.all([
......@@ -324,52 +334,117 @@
});
///////////////////////////////////////////////////////
// sync done (XXX - to finish)
// complete sync - one opml, 2 sub storages
///////////////////////////////////////////////////////
test("allready synced: nothing to do", function () {
expect(2);
test("complete storage sync", function () {
expect(4);
stop();
var test = this,
key,
doc_id = 'opml_foo',
doc_id = "http://example.com/rss.xml",
doc = {
title: "opml item foo",
htmlurl: "http://example.com/",
url: "http://example.com/rss.xml",
modified_date: "aftttt",
created_date: "adddb",
opml_title: "opml foo"
text: "instance foo",
type: "link",
opml_title: "opml foo",
created_date: "Thu, 12 Sep 2003 23:35:52 GMT",
modified_date: "Fri, 12 Sep 2003 23:45:37 GMT"
},
parent_id = generateHash(test.sub_opml_storage.url),
opml_item_id = generateHash(parent_id + doc_id),
opml_item = {
name: doc_id,
opml_title: doc.opml_title,
parent_id: parent_id,
reference: generateHash(parent_id + doc_id),
creation_date: doc.created_date,
title: doc.title,
type: "opml-item",
url: test.sub_opml_storage.url,
signature: generateHash(JSON.stringify(doc))
},
full_opml = new Blob([JSON.stringify(doc)]),
rss_id = "1102345",
rss_doc = {
"link": "http://www.domain.com/link.htm",
"date": "Tue, 29 Aug 2006 09:00:00 -0400",
"title": "Item Example",
"category": "ERROR",
"description": "This is an example of an Item",
"guid": "1102345",
"siteTitle": "instance foo",
"reference": "This is an example of an RSS feed",
"siteLink": "http://www.domain.com/link.htm",
"lastBuildDate": "Mon, 28 Aug 2006 11:12:55 -0400 "
},
// Sub OPML document (rss)
rss_feed_url = "http://example.com/rss.xml",
rss_item_id = generateHash(opml_item.reference + rss_feed_url + rss_id),
rss_item = {
name: rss_id,
opml_title: opml_item.opml_title,
parent_title: opml_item.title,
parent_id: opml_item.reference,
reference: rss_item_id,
title: rss_doc.title,
type: rss_doc.type || "rssmock-item",
url: rss_feed_url,
status: rss_doc.category,
creation_date: rss_doc.date,
signature: generateHash(JSON.stringify(rss_doc))
},
blob = new Blob([JSON.stringify(doc)]);
full_rss = new Blob([JSON.stringify(rss_doc)]),
json_id = "monitor.status",
json_doc = {
title: "document fooo",
status: "ERROR",
date: "Tue, 29 Aug 2006 09:00:00 -0400",
type: "global",
foo_p: "fooo parameter",
bar_p: "bar parameter",
total_error: 12345
},
// Sub OPML document (webhttp)
http_url = "http://example.com/",
json_item_id = generateHash(opml_item.reference + http_url + json_id),
json_item = {
name: json_id,
opml_title: opml_item.opml_title,
parent_title: opml_item.title,
parent_id: opml_item.reference,
reference: json_item_id,
title: json_doc.title,
type: json_doc.type,
url: http_url,
status: json_doc.status,
creation_date: json_doc.date,
signature: generateHash(JSON.stringify(json_doc))
},
full_json = new Blob([JSON.stringify(json_doc)]);
// initialise this storage here so we can put data
key = generateHash("http://example.com/opml.xml");
this.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "opmlmock",
options: this.opml_mock_options
});
putFullDoc(this.jio.__storage._remote_storage_dict[key], doc_id, doc)
.then(function () {
return test.jio.repair();
})
test.jio.repair()
.then(function () {
resetCount(test.opml_mock_options.count);
return test.jio.repair();
})
.then(function () {
var storage_doc = getOpmlElement(doc,
doc_id,
test.sub_opml_storage.url);
return RSVP.all([
equalStorage(test.jio, [[storage_doc.id, storage_doc.doc, blob]]),
equalStorage(test.jio, [[opml_item_id, opml_item, full_opml],
[rss_item_id, rss_item, full_rss],
[json_item_id, json_item, full_json]]),
equalsubStorageCallCount(
test.opml_mock_options.count,
{buildQuery: 1}
),
equalsubStorageCallCount(
test.rss_mock_options.count,
{buildQuery: 1}
),
equalsubStorageCallCount(
test.web_mock_options.count,
{buildQuery: 1}
)
]);
})
.fail(function (error) {
console.log(error);
ok(false, error);
})
.always(function () {
......@@ -378,96 +453,110 @@
});
///////////////////////////////////////////////////////
// complete sync - one opml, 2 sub storages
// document update
///////////////////////////////////////////////////////
test("complete storage sync", function () {
test("remote document modified", function () {
expect(4);
stop();
var test = this,
key,
doc_id = 'opml_foo',
doc_id = "http://example.com/rss.xml",
doc = {
title: "opml item foo",
htmlurl: "http://example.com/",
url: "http://example.com/rss.xml",
modified_date: "aftttt",
created_date: "adddb",
opml_title: "opml foo"
text: "instance foo",
type: "link",
opml_title: "opml foo",
created_date: "Thu, 12 Sep 2003 23:35:52 GMT",
modified_date: "Fri, 12 Sep 2003 23:45:37 GMT"
},
parent_id = generateHash(test.sub_opml_storage.url),
opml_item_id = generateHash(parent_id + doc_id),
opml_item = {
name: doc_id,
opml_title: doc.opml_title,
parent_id: parent_id,
reference: generateHash(parent_id + doc_id),
creation_date: doc.created_date,
title: doc.title,
type: "opml-item",
url: test.sub_opml_storage.url,
signature: generateHash(JSON.stringify(doc))
},
blob = new Blob([JSON.stringify(doc)]),
full_opml = new Blob([JSON.stringify(doc)]),
rss_id = "1102345",
rss_doc = {
date: "Tue, 29 Aug 2006 09:00:00 -0400",
description: "This is an example of an Item",
guid: "1102345",
lastBuildDate: "Mon, 28 Aug 2006 11:12:55 -0400 ",
reference: "This is an example of an RSS feed",
siteTitle: "RSS Example",
title: "Item Example",
status: "OK"
"link": "http://www.domain.com/link.htm",
"date": "Tue, 29 Aug 2006 09:00:00 -0400",
"title": "Item Example",
"category": "ERROR",
"description": "This is an example of an Item",
"guid": "1102345",
"siteTitle": "instance foo",
"reference": "This is an example of an RSS feed",
"siteLink": "http://www.domain.com/link.htm",
"lastBuildDate": "Mon, 28 Aug 2006 11:12:55 -0400 "
},
rss_blob = new Blob([JSON.stringify(rss_doc)]),
json_id = "promise_runner.status",
// Sub OPML document (rss)
rss_feed_url = test.sub_opml_storage.sub_storage_list[0].url,
rss_item_id = generateHash(opml_item.reference + rss_feed_url + rss_id),
rss_item2 = {
name: rss_id,
opml_title: opml_item.opml_title,
parent_title: opml_item.title,
parent_id: opml_item.reference,
reference: rss_item_id,
title: rss_doc.title,
type: rss_doc.type || "rssmock-item",
url: rss_feed_url,
status: rss_doc.category,
creation_date: rss_doc.date
},
rss_doc2 = JSON.parse(JSON.stringify(rss_doc)),
full_rss2,
json_id = "monitor.status",
json_doc = {
title: "promise fooo",
title: "document fooo",
status: "ERROR",
date: "Tue, 29 Aug 2006 09:00:00 -0400",
type: "promise",
type: "global",
foo_p: "fooo parameter",
bar_p: "bar parameter"
bar_p: "bar parameter",
total_error: 12345
},
json_blob = new Blob([JSON.stringify(json_doc)]),
opml_gen,
rss_gen,
json_gen;
opml_gen = getOpmlElement(doc, doc_id, test.sub_opml_storage.url);
rss_gen = getSubOpmlElement(
rss_doc,
rss_id,
opml_gen.doc,
test.sub_opml_storage.sub_storage_list[0].url,
"rssmock"
);
json_gen = getSubOpmlElement(
json_doc,
json_id,
opml_gen.doc,
test.sub_opml_storage.sub_storage_list[1].url,
"webmock"
);
// initialise this storage here so we can put data
key = generateHash(test.sub_opml_storage.url);
this.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "opmlmock",
options: this.opml_mock_options
});
// Sub OPML document (webhttp)
http_url = "http://example.com/",
json_item_id = generateHash(opml_item.reference + http_url + json_id),
json_item = {
name: json_id,
opml_title: opml_item.opml_title,
parent_title: opml_item.title,
parent_id: opml_item.reference,
reference: json_item_id,
title: json_doc.title,
type: json_doc.type,
url: http_url,
status: json_doc.status,
creation_date: json_doc.date,
signature: generateHash(JSON.stringify(json_doc))
},
full_json = new Blob([JSON.stringify(json_doc)]);
putFullDoc(this.jio.__storage._remote_storage_dict[key], doc_id, doc)
.then(function () {
// put rss doc
key = generateHash(opml_gen.doc.reference +
test.sub_opml_storage.sub_storage_list[0].url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "rssmock",
options: test.rss_mock_options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
rss_id, rss_doc);
})
.then(function () {
// put json doc
key = generateHash(opml_gen.doc.reference +
test.sub_opml_storage.sub_storage_list[1].url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "webmock",
options: test.web_mock_options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
json_id, json_doc);
})
/* Update rss document */
rss_doc2.date = "new rss date";
// new signature
rss_item2.signature = generateHash(JSON.stringify(rss_doc2));
// modified date
rss_item2.creation_date = rss_doc2.date;
// get the full rss item
full_rss2 = new Blob([JSON.stringify(rss_doc2)]);
test.jio.repair()
.then(function () {
test.rss_mock_options.mock.buildQuery = function () {
return [{id: rss_id, doc: rss_doc2, value: {}}];
};
resetCount(test.opml_mock_options.count);
resetCount(test.rss_mock_options.count);
resetCount(test.web_mock_options.count);
......@@ -475,9 +564,9 @@
})
.then(function () {
return RSVP.all([
equalStorage(test.jio, [[opml_gen.id, opml_gen.doc, blob],
[rss_gen.id, rss_gen.doc, rss_blob],
[json_gen.id, json_gen.doc, json_blob]]),
equalStorage(test.jio, [[opml_item_id, opml_item, full_opml],
[rss_item_id, rss_item2, full_rss2],
[json_item_id, json_item, full_json]]),
equalsubStorageCallCount(
test.opml_mock_options.count,
{buildQuery: 1}
......@@ -502,83 +591,120 @@
});
///////////////////////////////////////////////////////
// document update
// remote document deleted - non exist in result
///////////////////////////////////////////////////////
test("remote document modified", function () {
expect(4);
test("remote document deleted: empty result", function () {
expect(5);
stop();
var test = this,
key,
doc_id = 'opml_foo',
doc_id = "http://example.com/rss.xml",
doc = {
title: "opml item foo",
htmlurl: "http://example.com/",
url: "http://example.com/rss.xml",
modified_date: "aftttt",
created_date: "adddb",
opml_title: "opml foo"
text: "instance foo",
type: "link",
opml_title: "opml foo",
created_date: "Thu, 12 Sep 2003 23:35:52 GMT",
modified_date: "Fri, 12 Sep 2003 23:45:37 GMT"
},
parent_id = generateHash(test.sub_opml_storage.url),
opml_item_id = generateHash(parent_id + doc_id),
opml_item = {
name: doc_id,
opml_title: doc.opml_title,
parent_id: parent_id,
reference: generateHash(parent_id + doc_id),
creation_date: doc.created_date,
title: doc.title,
type: "opml-item",
url: test.sub_opml_storage.url,
signature: generateHash(JSON.stringify(doc))
},
blob = new Blob([JSON.stringify(doc)]),
full_opml = new Blob([JSON.stringify(doc)]),
rss_id = "1102345",
rss_doc = {
"link": "http://www.domain.com/link.htm",
"date": "Tue, 29 Aug 2006 09:00:00 -0400",
"title": "Item Example",
"category": "ERROR",
"description": "This is an example of an Item",
"guid": "1102345",
"siteTitle": "instance foo",
"reference": "This is an example of an RSS feed",
"siteLink": "http://www.domain.com/link.htm",
"lastBuildDate": "Mon, 28 Aug 2006 11:12:55 -0400 "
},
// Sub OPML document (rss)
rss_feed_url = "http://example.com/rss.xml",
rss_item_id = generateHash(opml_item.reference + rss_feed_url + rss_id),
rss_item = {
name: rss_id,
opml_title: opml_item.opml_title,
parent_title: opml_item.title,
parent_id: opml_item.reference,
reference: rss_item_id,
title: rss_doc.title,
type: rss_doc.type || "rssmock-item",
url: rss_feed_url,
status: rss_doc.category,
creation_date: rss_doc.date,
signature: generateHash(JSON.stringify(rss_doc))
},
full_rss = new Blob([JSON.stringify(rss_doc)]),
json_id = "monitor.status",
json_doc = {
title: "document fooo",
status: "ERROR",
date: "Tue, 29 Aug 2006 09:00:00 -0400",
description: "This is an example of an Item",
guid: "1102345",
lastBuildDate: "Mon, 28 Aug 2006 11:12:55 -0400 ",
reference: "This is an example of an RSS feed",
siteTitle: "RSS Example",
title: "Item Example",
status: "OK"
type: "global",
foo_p: "fooo parameter",
bar_p: "bar parameter",
total_error: 12345
},
opml_gen,
rss_gen,
rss_doc2 = JSON.parse(JSON.stringify(rss_doc)),
rss_blob2 = new Blob([JSON.stringify(rss_doc2)]);
opml_gen = getOpmlElement(doc, doc_id, test.sub_opml_storage.url);
rss_gen = getSubOpmlElement(
rss_doc2,
rss_id,
opml_gen.doc,
test.sub_opml_storage.sub_storage_list[0].url,
"rssmock"
);
// initialise this storage here so we can put data
key = generateHash(test.sub_opml_storage.url);
this.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "opmlmock",
options: this.opml_mock_options
});
// Sub OPML document (webhttp)
http_url = "http://example.com/",
json_item_id = generateHash(opml_item.reference + http_url + json_id),
json_item = {
name: json_id,
opml_title: opml_item.opml_title,
parent_title: opml_item.title,
parent_id: opml_item.reference,
reference: json_item_id,
title: json_doc.title,
type: json_doc.type,
url: http_url,
status: json_doc.status,
creation_date: json_doc.date,
signature: generateHash(JSON.stringify(json_doc))
},
full_json = new Blob([JSON.stringify(json_doc)]);
putFullDoc(this.jio.__storage._remote_storage_dict[key], doc_id, doc)
.then(function () {
// put rss doc
key = generateHash(opml_gen.doc.reference +
test.sub_opml_storage.sub_storage_list[0].url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "rssmock",
options: test.rss_mock_options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
rss_id, rss_doc);
})
new RSVP.Queue()
.then(function () {
return test.jio.repair();
})
.then(function () {
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
rss_id, rss_doc2);
return RSVP.all([
equalStorage(test.jio, [[opml_item_id, opml_item, full_opml],
[rss_item_id, rss_item, full_rss],
[json_item_id, json_item, full_json]])
]);
})
.then(function () {
test.rss_mock_options.mock.buildQuery = function () {
return [];
};
resetCount(test.opml_mock_options.count);
resetCount(test.rss_mock_options.count);
resetCount(test.web_mock_options.count);
return test.jio.repair();
})
.then(function () {
return RSVP.all([
equalStorage(test.jio, [[opml_gen.id, opml_gen.doc, blob],
[rss_gen.id, rss_gen.doc, rss_blob2]]),
equalStorage(test.jio, [[opml_item_id, opml_item, full_opml],
[json_item_id, json_item, full_json]]),
equalsubStorageCallCount(
test.opml_mock_options.count,
{buildQuery: 1}
......@@ -589,12 +715,11 @@
),
equalsubStorageCallCount(
test.web_mock_options.count,
{}
{buildQuery: 1}
)
]);
})
.fail(function (error) {
console.log(error);
ok(false, error);
})
.always(function () {
......@@ -603,86 +728,126 @@
});
///////////////////////////////////////////////////////
// document remove
// some document remove - id has changed
///////////////////////////////////////////////////////
test("remote document deleted", function () {
test("remote document removed", function () {
expect(5);
stop();
var test = this,
key,
doc_id = 'opml_foo',
doc_id = "http://example.com/rss.xml",
doc = {
title: "opml item foo",
htmlurl: "http://example.com/",
url: "http://example.com/rss.xml",
modified_date: "aftttt",
created_date: "adddb",
opml_title: "opml foo"
text: "instance foo",
type: "link",
opml_title: "opml foo",
created_date: "Thu, 12 Sep 2003 23:35:52 GMT",
modified_date: "Fri, 12 Sep 2003 23:45:37 GMT"
},
parent_id = generateHash(test.sub_opml_storage.url),
opml_item_id = generateHash(parent_id + doc_id),
opml_item = {
name: doc_id,
opml_title: doc.opml_title,
parent_id: parent_id,
reference: generateHash(parent_id + doc_id),
creation_date: doc.created_date,
title: doc.title,
type: "opml-item",
url: test.sub_opml_storage.url,
signature: generateHash(JSON.stringify(doc))
},
blob = new Blob([JSON.stringify(doc)]),
full_opml = new Blob([JSON.stringify(doc)]),
rss_id = "1102345",
rss_doc = {
"link": "http://www.domain.com/link.htm",
"date": "Tue, 29 Aug 2006 09:00:00 -0400",
"title": "Item Example",
"category": "ERROR",
"description": "This is an example of an Item",
"guid": "1102345",
"siteTitle": "instance foo",
"reference": "This is an example of an RSS feed",
"siteLink": "http://www.domain.com/link.htm",
"lastBuildDate": "Mon, 28 Aug 2006 11:12:55 -0400 "
},
// Sub OPML document (rss)
rss_feed_url = "http://example.com/rss.xml",
rss_item_id = generateHash(opml_item.reference + rss_feed_url + rss_id),
rss_item = {
name: rss_id,
opml_title: opml_item.opml_title,
parent_title: opml_item.title,
parent_id: opml_item.reference,
reference: rss_item_id,
title: rss_doc.title,
type: rss_doc.type || "rssmock-item",
url: rss_feed_url,
status: rss_doc.category,
creation_date: rss_doc.date,
signature: generateHash(JSON.stringify(rss_doc))
},
full_rss = new Blob([JSON.stringify(rss_doc)]),
json_id = "monitor.status",
json_doc = {
title: "document fooo",
status: "ERROR",
date: "Tue, 29 Aug 2006 09:00:00 -0400",
description: "This is an example of an Item",
guid: "1102345",
lastBuildDate: "Mon, 28 Aug 2006 11:12:55 -0400 ",
reference: "This is an example of an RSS feed",
siteTitle: "RSS Example",
title: "Item Example",
status: "OK"
type: "global",
foo_p: "fooo parameter",
bar_p: "bar parameter",
total_error: 12345
},
rss_blob = new Blob([JSON.stringify(rss_doc)]),
opml_gen,
rss_gen;
opml_gen = getOpmlElement(doc, doc_id, test.sub_opml_storage.url);
rss_gen = getSubOpmlElement(
rss_doc,
rss_id,
opml_gen.doc,
test.sub_opml_storage.sub_storage_list[0].url,
"rssmock"
);
// initialise this storage here so we can put data
key = generateHash(test.sub_opml_storage.url);
this.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "opmlmock",
options: this.opml_mock_options
});
// Sub OPML document (webhttp)
http_url = "http://example.com/",
json_item_id = generateHash(opml_item.reference + http_url + json_id),
json_item = {
name: json_id,
opml_title: opml_item.opml_title,
parent_title: opml_item.title,
parent_id: opml_item.reference,
reference: json_item_id,
title: json_doc.title,
type: json_doc.type,
url: http_url,
status: json_doc.status,
creation_date: json_doc.date,
signature: generateHash(JSON.stringify(json_doc))
},
full_json = new Blob([JSON.stringify(json_doc)]),
/* rss doc 2 with different id */
rss_id2 = "1102345-new",
rss_item2_id = generateHash(opml_item.reference + rss_feed_url + rss_id2),
rss_item2 = JSON.parse(JSON.stringify(rss_item));
putFullDoc(this.jio.__storage._remote_storage_dict[key], doc_id, doc)
.then(function () {
// put rss doc
key = generateHash(opml_gen.doc.reference +
test.sub_opml_storage.sub_storage_list[0].url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "rssmock",
options: test.rss_mock_options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
rss_id, rss_doc);
})
.then(function () {
return test.jio.repair();
})
rss_item2.name = rss_id2;
rss_item2.reference = rss_item2_id;
test.jio.repair()
.then(function () {
return RSVP.all([
equalStorage(test.jio, [[opml_gen.id, opml_gen.doc, blob],
[rss_gen.id, rss_gen.doc, rss_blob]])
equalStorage(test.jio, [[opml_item_id, opml_item, full_opml],
[rss_item_id, rss_item, full_rss],
[json_item_id, json_item, full_json]])
]);
})
.then(function () {
test.rss_mock_options.mock.buildQuery = function () {
return [];
// return a different document
return [{id: rss_id2, doc: rss_doc, value: {}}];
};
resetCount(test.opml_mock_options.count);
resetCount(test.rss_mock_options.count);
resetCount(test.web_mock_options.count);
return test.jio.repair();
})
.then(function () {
return RSVP.all([
equalStorage(test.jio, [[opml_gen.id, opml_gen.doc, blob]]),
equalStorage(test.jio, [[opml_item_id, opml_item, full_opml],
[json_item_id, json_item, full_json],
[rss_item2_id, rss_item2, full_rss]]),
equalsubStorageCallCount(
test.opml_mock_options.count,
{buildQuery: 1}
......@@ -693,7 +858,7 @@
),
equalsubStorageCallCount(
test.web_mock_options.count,
{}
{buildQuery: 1}
)
]);
})
......@@ -707,67 +872,77 @@
});
///////////////////////////////////////////////////////
// complete sync - many opml (2 opmls, 4 sub storages)
// complete sync - 2 opmls, 3 sub storages
///////////////////////////////////////////////////////
test("multi opml storage sync", function () {
expect(7);
expect(6);
stop();
var test = this,
key,
doc_id = 'opml_foo',
doc_id = "http://example.com/rss.xml",
doc = {
title: "opml item foo",
htmlurl: "http://example.com/",
url: "http://example.com/rss.xml",
modified_date: "aftttt",
created_date: "adddb",
opml_title: "opml foo"
text: "instance foo",
type: "link",
opml_title: "opml foo",
created_date: "Thu, 12 Sep 2003 23:35:52 GMT",
modified_date: "Fri, 12 Sep 2003 23:45:37 GMT"
},
blob = new Blob([JSON.stringify(doc)]),
full_opml = new Blob([JSON.stringify(doc)]),
rss_id = "1102345",
rss_doc = {
date: "Tue, 29 Aug 2006 09:00:00 -0400",
description: "This is an example of an Item",
guid: "1102345",
lastBuildDate: "Mon, 28 Aug 2006 11:12:55 -0400 ",
reference: "This is an example of an RSS feed",
siteTitle: "RSS Example",
title: "Item Example",
status: "OK"
"link": "http://www.domain.com/link.htm",
"date": "Tue, 29 Aug 2006 09:00:00 -0400",
"title": "Item Example",
"category": "ERROR",
"description": "This is an example of an Item",
"guid": "1102345",
"siteTitle": "instance foo",
"reference": "This is an example of an RSS feed",
"siteLink": "http://www.domain.com/link.htm",
"lastBuildDate": "Mon, 28 Aug 2006 11:12:55 -0400 "
},
rss_blob = new Blob([JSON.stringify(rss_doc)]),
json_id = "promise_runner.status",
full_rss = new Blob([JSON.stringify(rss_doc)]),
json_id = "monitor.status",
json_doc = {
title: "promise fooo",
title: "document fooo",
status: "ERROR",
date: "Tue, 29 Aug 2006 09:00:00 -0400",
type: "promise",
type: "global",
foo_p: "fooo parameter",
bar_p: "bar parameter"
bar_p: "bar parameter",
total_error: 12345
},
json_blob = new Blob([JSON.stringify(json_doc)]),
gen_dict = {};
full_json = new Blob([JSON.stringify(json_doc)]),
item_dict = {},
rss_url = "http://example.com/rss.xml",
rss2_url = "http://example2.com/rss.xml",
http_url = "http://example.com/";
// update storage with 2 opmls
// opml2 has only rss feed substorage
this.sub_opml_storage2 = {
type: "opmlmock",
options: JSON.parse(JSON.stringify(this.opml_mock_options)),
options: {
mock: {
},
count: {}
},
url: "http://example2.com/opml.xml",
sub_storage_list: [
{
type: "rssmock",
url: "http://example2.com/rss.xml",
has_include_docs: true,
options: JSON.parse(JSON.stringify(this.rss_mock_options))
},
{
type: "webmock",
url: "http://example2.com/data/",
has_include_docs: true,
options: JSON.parse(JSON.stringify(this.web_mock_options))
options: {
mock: {
},
count: {}
}
}
],
basic_login: "YWRtaW46endfEzrJUZGw="
]
};
this.jio = jIO.createJIO({
type: "replicatedopml",
......@@ -786,117 +961,83 @@
}
});
gen_dict.opml = getOpmlElement(doc, doc_id, test.sub_opml_storage.url);
gen_dict.opml2 = getOpmlElement(doc, doc_id, test.sub_opml_storage2.url);
gen_dict.rss = getSubOpmlElement(
rss_doc,
rss_id,
gen_dict.opml.doc,
test.sub_opml_storage.sub_storage_list[0].url,
"rssmock"
);
gen_dict.json = getSubOpmlElement(
json_doc,
json_id,
gen_dict.opml.doc,
test.sub_opml_storage.sub_storage_list[1].url,
"webmock"
);
gen_dict.rss2 = getSubOpmlElement(
rss_doc,
rss_id,
gen_dict.opml2.doc,
test.sub_opml_storage2.sub_storage_list[0].url,
"rssmock"
);
gen_dict.json2 = getSubOpmlElement(
json_doc,
json_id,
gen_dict.opml2.doc,
test.sub_opml_storage2.sub_storage_list[1].url,
"webmock"
);
// initialise this storage here so we can put data
key = generateHash(test.sub_opml_storage.url);
this.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "opmlmock",
options: this.opml_mock_options
});
/* Expected item in indexeddb*/
item_dict.opml = {
parent_id: generateHash(test.sub_opml_storage.url),
reference: generateHash(generateHash(test.sub_opml_storage.url) + doc_id),
name: doc_id,
opml_title: doc.opml_title,
creation_date: doc.created_date,
title: doc.title,
type: "opml-item",
url: test.sub_opml_storage.url,
signature: generateHash(JSON.stringify(doc))
};
item_dict.opml2 = {
parent_id: generateHash(test.sub_opml_storage2.url),
reference: generateHash(
generateHash(test.sub_opml_storage2.url) + doc_id
),
name: doc_id,
opml_title: doc.opml_title,
creation_date: doc.created_date,
title: doc.title,
type: "opml-item",
url: test.sub_opml_storage2.url,
signature: generateHash(JSON.stringify(doc))
};
item_dict.rss = {
name: rss_id,
opml_title: item_dict.opml.opml_title,
parent_title: item_dict.opml.title,
parent_id: item_dict.opml.reference,
reference: generateHash(item_dict.opml.reference + rss_url + rss_id),
title: rss_doc.title,
type: rss_doc.type || "rssmock-item",
url: rss_url,
status: rss_doc.category,
creation_date: rss_doc.date,
signature: generateHash(JSON.stringify(rss_doc))
};
item_dict.rss2 = {
name: rss_id,
opml_title: item_dict.opml2.opml_title,
parent_title: item_dict.opml2.title,
parent_id: item_dict.opml2.reference,
reference: generateHash(item_dict.opml2.reference + rss2_url + rss_id),
title: rss_doc.title,
type: "rssmock-item",
url: rss2_url,
status: rss_doc.category,
creation_date: rss_doc.date,
signature: generateHash(JSON.stringify(rss_doc))
};
item_dict.json = {
name: json_id,
opml_title: item_dict.opml.opml_title,
parent_title: item_dict.opml.title,
parent_id: item_dict.opml.reference,
reference: generateHash(item_dict.opml.reference + http_url + json_id),
title: json_doc.title,
type: json_doc.type,
url: http_url,
status: json_doc.status,
creation_date: json_doc.date,
signature: generateHash(JSON.stringify(json_doc))
};
putFullDoc(this.jio.__storage._remote_storage_dict[key], doc_id, doc)
new RSVP.Queue()
.then(function () {
// put second opml doc
key = generateHash(test.sub_opml_storage2.url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "opmlmock",
options: test.sub_opml_storage2.options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
doc_id, doc);
})
.then(function () {
// put rss doc1
key = generateHash(gen_dict.opml.doc.reference +
test.sub_opml_storage.sub_storage_list[0].url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "rssmock",
options: test.rss_mock_options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
rss_id, rss_doc);
})
.then(function () {
// put json doc1
key = generateHash(gen_dict.opml.doc.reference +
test.sub_opml_storage.sub_storage_list[1].url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "webmock",
options: test.web_mock_options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
json_id, json_doc);
})
.then(function () {
// put rss doc2
key = generateHash(gen_dict.opml2.doc.reference +
test.sub_opml_storage2.sub_storage_list[0].url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "rssmock",
options: test.sub_opml_storage2.sub_storage_list[0].options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
rss_id, rss_doc);
})
.then(function () {
// put json doc2
key = generateHash(gen_dict.opml2.doc.reference +
test.sub_opml_storage2.sub_storage_list[1].url);
test.jio.__storage._remote_storage_dict[key] = jIO.createJIO({
type: "webmock",
options: test.sub_opml_storage2.sub_storage_list[1].options
});
return putFullDoc(test.jio.__storage._remote_storage_dict[key],
json_id, json_doc);
})
.then(function () {
resetCount(test.opml_mock_options.count);
resetCount(test.rss_mock_options.count);
resetCount(test.web_mock_options.count);
resetCount(test.sub_opml_storage2.options.count);
resetCount(test.sub_opml_storage2.sub_storage_list[0].options.count);
resetCount(test.sub_opml_storage2.sub_storage_list[1].options.count);
return test.jio.repair();
})
.then(function () {
return RSVP.all([
equalStorage(test.jio,
[[gen_dict.opml.id, gen_dict.opml.doc, blob],
[gen_dict.opml2.id, gen_dict.opml2.doc, blob],
[gen_dict.rss.id, gen_dict.rss.doc, rss_blob],
[gen_dict.rss2.id, gen_dict.rss2.doc, rss_blob],
[gen_dict.json.id, gen_dict.json.doc, json_blob],
[gen_dict.json2.id, gen_dict.json2.doc, json_blob]]
[[item_dict.opml.reference, item_dict.opml, full_opml],
[item_dict.rss.reference, item_dict.rss, full_rss],
[item_dict.json.reference, item_dict.json, full_json],
[item_dict.opml2.reference, item_dict.opml2, full_opml],
[item_dict.rss2.reference, item_dict.rss2, full_rss]]
),
equalsubStorageCallCount(
test.opml_mock_options.count,
......@@ -917,10 +1058,6 @@
equalsubStorageCallCount(
test.sub_opml_storage2.sub_storage_list[0].options.count,
{buildQuery: 1}
),
equalsubStorageCallCount(
test.sub_opml_storage2.sub_storage_list[1].options.count,
{buildQuery: 1}
)
]);
})
......@@ -933,4 +1070,4 @@
});
});
}(QUnit, jIO, Blob, Rusha, console));
\ No newline at end of file
}(QUnit, jIO, Blob, Rusha, sinon, console));
\ No newline at end of file
......@@ -14,15 +14,15 @@
function getOpmlOutlineAsDict(outline) {
var outline_dict = {
title: outline.getAttribute('title') || '',
htmlurl: outline.getAttribute('htmlUrl') || '',
xmlurl: outline.getAttribute('xmlUrl') || '',
url: outline.getAttribute('url') || '',
text: outline.getAttribute('text') || '',
type: outline.getAttribute('type') || '',
version: outline.getAttribute('version') || '',
created: outline.getAttribute('created') || '',
category: outline.getAttribute('category') || ''
title: outline.getAttribute('title') || dummy.textContent,
htmlurl: outline.getAttribute('htmlUrl') || dummy.textContent,
xmlurl: outline.getAttribute('xmlUrl') || dummy.textContent,
url: outline.getAttribute('url') || dummy.textContent,
text: outline.getAttribute('text') || dummy.textContent,
type: outline.getAttribute('type') || dummy.textContent,
version: outline.getAttribute('version') || dummy.textContent,
created: outline.getAttribute('created') || dummy.textContent,
category: outline.getAttribute('category') || dummy.textContent
};
return outline_dict;
}
......@@ -122,6 +122,9 @@
.push(function (response) {
var element,
result;
if (!response.target.responseText) {
throw new jIO.util.jIOError("Cannot find document", 404);
}
element = new DOMParser().parseFromString(
response.target.responseText,
"text/xml"
......
......@@ -122,7 +122,11 @@
};*/
ReplicatedOPMLStorage.prototype.hasCapacity = function (capacity) {
return (capacity === "list") || (capacity === "include");
if (capacity === 'include') {
return true;
}
return this._local_sub_storage.hasCapacity.apply(this._local_sub_storage,
arguments);
};
ReplicatedOPMLStorage.prototype.getAttachment = function () {
......@@ -135,10 +139,8 @@
arguments);
};
function getSubOpmlStorageDescription(spec, opml_doc, basic_login) {
var storage_spec;
function getSubOpmlStorageDescription(storage_spec, opml_doc, basic_login) {
storage_spec = JSON.parse(JSON.stringify(spec));
if (storage_spec.basic_login === undefined && basic_login !== undefined) {
storage_spec.basic_login = basic_login;
}
......@@ -146,7 +148,6 @@
if (storage_spec.url_attribute !== undefined &&
opml_doc.hasOwnProperty(storage_spec.url_attribute)) {
storage_spec.url = opml_doc[storage_spec.url_attribute];
delete storage_spec.url_attribute;
} else if (storage_spec.url_path !== undefined) {
storage_spec.url_path = storage_spec.url_path.replace(
new RegExp("^[/]+"),
......@@ -156,7 +157,6 @@
new RegExp("[/]+$"),
""
) + "/" + storage_spec.url_path;
delete storage_spec.url_path;
}
// XXX - for compatibility, remove url with jio_private path
storage_spec.url = storage_spec.url.replace("jio_private", "private");
......@@ -215,6 +215,7 @@
parent_title: opml_doc.title,
opml_title: opml_doc.opml_title,
type: storage_spec.type,
current_doc: {},
result: {
data: {
total_rows: 0
......@@ -223,16 +224,35 @@
url: url
};
return sub_storage.allDocs(options)
.push(function (result) {
result_dict.result = result;
return result_dict;
}, function (error) {
.push(undefined, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
console.log(error);
return result_dict;
return undefined;
}
throw error;
//throw error;
// throw will cancel all others allDocs, this is not wanted
console.log(error);
return undefined;
})
.push(function (result) {
if (result === undefined) {
return {data: {total_rows: 0}};
}
result_dict.result = result;
return context._local_sub_storage.allDocs({
select_list: ["signature"],
query: '(parent_id: "' + parent_id + '") AND (url:"' + url + '")'
});
})
.push(function (all_document) {
var i;
for (i = 0; i < all_document.data.total_rows; i += 1) {
result_dict.current_doc[
all_document.data.rows[i].id
] = all_document.data.rows[i].value;
}
return result_dict;
});
}
......@@ -240,6 +260,8 @@
var opml_storage,
opml_document_list = [],
document_attachment_dict = {},
delete_key_list = [],
current_opml_dict = {},
id;
id = generateHash(opml_url);
......@@ -248,40 +270,44 @@
.push(undefined, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return [[], {}];
return {data: {total_rows: 0}};
}
//throw error;
// throw will cancel all remaning tasks
return {data: {total_rows: 0}};
})
.push(function (opml_result) {
return RSVP.all([
opml_result,
context._local_sub_storage.allDocs({
select_list: ["signature"],
query: '(parent_id: "' + id + '")'
})
]);
})
.push(function (result_list) {
var i;
for (i = 0; i < result_list[1].data.total_rows; i += 1) {
current_opml_dict[
result_list[1].data.rows[i].id
] = result_list[1].data.rows[i].value;
}
throw error;
return result_list[0];
})
.push(function (opml_result_list) {
var j,
i,
item,
signature,
skip_add = false,
id_hash,
result_list = [];
for (i = 0; i < opml_result_list.data.total_rows; i += 1) {
item = opml_result_list.data.rows[i];
id_hash = generateHash(id + item.id);
signature = generateHash(JSON.stringify(item.doc));
opml_document_list.push({
id: id_hash,
doc: {
type: "opml-item",
name: item.id,
reference: id_hash,
parent_id: id,
creation_date: item.doc.created_date,
url: opml_url,
title: item.doc.title,
parent_title: undefined,
opml_title: item.doc.opml_title,
status: undefined
}
});
document_attachment_dict[id_hash] = {
name: item.id,
doc: item.doc
};
for (j = 0; j < opml_spec.sub_storage_list.length; j += 1) {
result_list.push(loadSubStorage(
context,
......@@ -291,7 +317,40 @@
opml_spec.basic_login
));
}
if (current_opml_dict.hasOwnProperty(id_hash)) {
if (current_opml_dict[id_hash].signature === signature) {
// the document was not modified, delete and skip add
delete current_opml_dict[id_hash];
skip_add = true;
}
delete current_opml_dict[id_hash];
}
if (!skip_add) {
opml_document_list.push({
id: id_hash,
doc: {
type: "opml-item",
name: item.id,
reference: id_hash,
parent_id: id,
creation_date: item.doc.created_date,
url: opml_url,
title: item.doc.title,
parent_title: undefined,
opml_title: item.doc.opml_title,
status: undefined,
signature: signature
}
});
document_attachment_dict[id_hash] = {
name: item.id,
doc: item.doc
};
}
}
delete_key_list.push.apply(delete_key_list,
Object.keys(current_opml_dict));
return RSVP.all(result_list);
})
.push(function (result_list) {
......@@ -300,7 +359,8 @@
function applyItemToTree(item, item_result) {
var id_hash,
element;
element,
signature;
id_hash = generateHash(item_result.parent_id +
item_result.url + item.id);
......@@ -309,6 +369,19 @@
} else {
element = item.value;
}
// Generating document signature
signature = generateHash(JSON.stringify(element));
if (item_result.current_doc.hasOwnProperty(id_hash)) {
if (item_result.current_doc[id_hash].signature === signature) {
// the document was not modified delete and return
delete item_result.current_doc[id_hash];
return;
}
// the document exists and has changed
delete item_result.current_doc[id_hash];
}
opml_document_list.push({
id: id_hash,
doc: {
......@@ -321,7 +394,8 @@
status: (element.status || element.category),
title: (element.source || element.title),
parent_title: item_result.parent_title,
opml_title: item_result.opml_title
opml_title: item_result.opml_title,
signature: signature
}
});
document_attachment_dict[id_hash] = {
......@@ -337,112 +411,106 @@
result_list[i]
);
}
delete_key_list.push.apply(delete_key_list,
Object.keys(result_list[i].current_doc));
}
return [opml_document_list, document_attachment_dict];
return [opml_document_list, document_attachment_dict, delete_key_list];
});
}
function syncOpmlStorage(context) {
var i,
promise_list = [];
for (i = 0; i < context._opml_storage_list.length; i += 1) {
promise_list.push(
getOpmlTree(context,
context._opml_storage_list[i].url,
context._opml_storage_list[i])
);
function pushDocumentToStorage(context, document_list, attachment_dict,
delete_key_list) {
var document_queue = new RSVP.Queue(),
i;
function pushDocument(id, element, attachment) {
document_queue
.push(function () {
return context._local_sub_storage.put(id, element);
})
.push(function () {
return context._local_sub_storage.putAttachment(
id,
attachment.name,
new Blob([JSON.stringify(attachment.doc)])
);
});
}
return RSVP.all(promise_list);
}
function repairLocalStorage(context, new_document_list, document_key_list) {
var j,
promise_list = [];
for (i = 0; i < document_list.length; i += 1) {
pushDocument(
document_list[i].id,
document_list[i].doc,
attachment_dict[document_list[i].id]
);
}
return document_queue
.push(function () {
var k,
remove_queue = new RSVP.Queue();
// remove all document which were not updated
function removeDocument(key) {
remove_queue
.push(function () {
return context._local_sub_storage.get(key);
})
.push(undefined, function (error) {
throw error;
})
.push(function (element) {
return context._local_sub_storage.removeAttachment(
key,
element.name
);
})
.push(function () {
return context._local_sub_storage.remove(key);
})
.push(undefined, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return {};
}
throw error;
});
}
function pushDocumentToStorage(document_list, attachment_dict) {
var document_queue = new RSVP.Queue(),
doc_index,
i;
for (k = 0; k < delete_key_list.length; k += 1) {
removeDocument(delete_key_list[k]);
}
return remove_queue;
});
}
function pushDocument(id, element, attachment) {
document_queue
.push(function () {
return context._local_sub_storage.put(id, element);
})
.push(function () {
return context._local_sub_storage.putAttachment(
id,
attachment.name,
new Blob([JSON.stringify(attachment.doc)])
);
});
}
function syncOpmlStorage(context) {
var i,
opml_queue = new RSVP.Queue();
for (i = 0; i < document_list.length; i += 1) {
doc_index = document_key_list.indexOf(document_list[i].id);
if (doc_index !== -1) {
delete document_key_list[doc_index];
}
pushDocument(
document_list[i].id,
document_list[i].doc,
attachment_dict[document_list[i].id]
);
}
return document_queue
function syncFullOpml(url, storage_spec) {
return opml_queue
.push(function () {
var k,
remove_queue = new RSVP.Queue();
// remove all document which were not updated
function removeDocument(key) {
remove_queue
.push(function () {
return context._local_sub_storage.get(key);
})
.push(undefined, function (error) {
throw error;
})
.push(function (element) {
return context._local_sub_storage.removeAttachment(
key,
element.name
);
})
.push(function () {
return context._local_sub_storage.remove(key);
})
.push(undefined, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return {};
}
throw error;
});
}
for (k = 0; k < document_key_list.length; k += 1) {
if (document_key_list[k] !== undefined) {
removeDocument(document_key_list[k]);
}
}
return remove_queue;
return getOpmlTree(context, url, storage_spec);
})
.push(function (result_list) {
return pushDocumentToStorage(
context,
result_list[0],
result_list[1],
result_list[2]
);
});
}
for (j = 0; j < new_document_list.length; j += 1) {
promise_list.push(pushDocumentToStorage(
new_document_list[j][0],
new_document_list[j][1]
));
for (i = 0; i < context._opml_storage_list.length; i += 1) {
syncFullOpml(context._opml_storage_list[i].url,
context._opml_storage_list[i]);
}
return RSVP.all(promise_list);
return opml_queue;
}
ReplicatedOPMLStorage.prototype.repair = function () {
var context = this,
argument_list = arguments,
local_storage_index_list = [];
argument_list = arguments;
return new RSVP.Queue()
.push(function () {
......@@ -452,21 +520,8 @@
);
})
.push(function () {
return context._local_sub_storage.allDocs();
})
.push(function (document_index) {
var i;
for (i = 0; i < document_index.data.total_rows; i += 1) {
local_storage_index_list.push(document_index.data.rows[i].id);
}
return syncOpmlStorage(context);
})
.push(function (result_list) {
return repairLocalStorage(context,
result_list,
local_storage_index_list);
});
};
jIO.addStorage('replicatedopml', ReplicatedOPMLStorage);
......
......@@ -152,6 +152,9 @@
.push(function (response) {
var element,
item;
if (!response.target.responseText) {
throw new jIO.util.jIOError("Cannot find document", 404);
}
element = new DOMParser().parseFromString(
response.target.responseText,
"text/xml"
......
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