Commit a7eed05b authored by preetwinder's avatar preetwinder

Use replicatestorage to repair

parent 8b3842f6
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
throw new TypeError("IndexStorage2 'index_keys' description property " + throw new TypeError("IndexStorage2 'index_keys' description property " +
"must be an Array"); "must be an Array");
} }
this._sub_storage_description = description.sub_storage;
this._sub_storage = jIO.createJIO(description.sub_storage); this._sub_storage = jIO.createJIO(description.sub_storage);
this._database_name = "jio:" + description.database; this._database_name = "jio:" + description.database;
this._index_keys = description.index_keys || []; this._index_keys = description.index_keys || [];
...@@ -68,38 +69,6 @@ ...@@ -68,38 +69,6 @@
return doc; return doc;
} }
function getDocs(storage) {
var promise_hash = {}, i;
try {
storage.hasCapacity('include');
return storage.allDocs({include_docs: true});
} catch (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 501)) {
storage.hasCapacity('list');
return storage.allDocs()
.push(function (result) {
var id;
for (i = 0; i < result.data.total_rows; i += 1) {
id = result.data.rows[i].id;
promise_hash[id] = storage.get(id);
}
return RSVP.hash(promise_hash);
})
.push(function (temp_result) {
var final_result = {data: {rows: []}}, keys;
keys = Object.keys(temp_result);
for (i = 0; i < keys.length; i += 1) {
final_result.data.rows.push({id: keys[i],
doc: temp_result[keys[i]]});
}
final_result.data.total_rows = final_result.data.rows.length;
return final_result;
});
}
throw error;
}
}
function waitForIDBRequest(request) { function waitForIDBRequest(request) {
return new RSVP.Promise(function (resolve, reject) { return new RSVP.Promise(function (resolve, reject) {
request.onerror = reject; request.onerror = reject;
...@@ -107,10 +76,55 @@ ...@@ -107,10 +76,55 @@
}); });
} }
function handleUpgradeNeeded(evt, index_keys, repair_storage) { function VirtualIDB(description) {
this._write_operations = description.write_operations;
}
VirtualIDB.prototype.put = function () {
this._write_operations.put.push(arguments);
};
VirtualIDB.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'select');
};
VirtualIDB.prototype.get = function (id) {
throw new jIO.util.jIOError("Cannot find document: " + id, 404);
};
VirtualIDB.prototype.buildQuery = function () {
return [];
};
jIO.addStorage("virtualidb", VirtualIDB);
function getRepairStorage(write_operations, sub_storage_description) {
return jIO.createJIO({
type: "replicate",
local_sub_storage: sub_storage_description,
check_local_modification: false,
check_local_deletion: false,
check_local_creation: true,
check_remote_modification: false,
check_remote_creation: false,
check_remote_deletion: false,
remote_sub_storage: {
type: "virtualidb",
write_operations: write_operations,
},
signature_sub_storage: {
type: "query",
sub_storage: {
type: "memory"
}
}
});
}
function handleUpgradeNeeded(evt, index_keys, sub_storage_description) {
var db = evt.target.result, store, i, current_indices, required_indices, var db = evt.target.result, store, i, current_indices, required_indices,
put_promise_list = [], docs_promise, put_promise_list = [], repair_promise, repeatUntilPromiseFulfilled,
repeatUntilPromiseFulfilled; write_operations;
required_indices = new Set(index_keys.map(function (name) { required_indices = new Set(index_keys.map(function (name) {
return 'Index-' + name; return 'Index-' + name;
})); }));
...@@ -142,35 +156,34 @@ ...@@ -142,35 +156,34 @@
'doc.' + index_keys[i], { unique: false }); 'doc.' + index_keys[i], { unique: false });
} }
docs_promise = getDocs(repair_storage); write_operations = {put: []};
repair_promise = getRepairStorage(write_operations,
sub_storage_description).repair();
repeatUntilPromiseFulfilled = function repeatUntilPromiseFulfilled(req) { repeatUntilPromiseFulfilled = function repeatUntilPromiseFulfilled(req) {
req.onsuccess = function () { req.onsuccess = function () {
if (docs_promise.isRejected) { if (repair_promise.isRejected) {
throw new jIO.util.jIOError(docs_promise.rejectedReason.message, evt.target.transaction.abort();
docs_promise.rejectedReason.status_code); return;
} }
if (docs_promise.isFulfilled) { if (repair_promise.isFulfilled) {
for (i = 0; i < docs_promise.fulfillmentValue.data.total_rows; for (i = 0; i < write_operations.put.length; i += 1) {
i += 1) {
put_promise_list.push(waitForIDBRequest(store.put({ put_promise_list.push(waitForIDBRequest(store.put({
id: docs_promise.fulfillmentValue.data.rows[i].id, id: write_operations.put[i][0],
doc: filterDocValues( doc: filterDocValues(write_operations.put[i][1], index_keys)
docs_promise.fulfillmentValue.data.rows[i].doc,
index_keys
)
}))); })));
} }
write_operations.put = [];
return RSVP.all(put_promise_list); return RSVP.all(put_promise_list);
} }
repeatUntilPromiseFulfilled(store.getAll()); return repeatUntilPromiseFulfilled(store.getAll());
}; };
}; };
repeatUntilPromiseFulfilled(store.getAll()); repeatUntilPromiseFulfilled(store.getAll());
} }
} }
function waitForOpenIndexedDB(db_name, version, index_keys, repair_storage, function waitForOpenIndexedDB(db_name, version, index_keys,
callback) { sub_storage_description, callback) {
function resolver(resolve, reject) { function resolver(resolve, reject) {
// Open DB // // Open DB //
var request = indexedDB.open(db_name, version); var request = indexedDB.open(db_name, version);
...@@ -205,7 +218,7 @@ ...@@ -205,7 +218,7 @@
// Create DB if necessary // // Create DB if necessary //
request.onupgradeneeded = function (evt) { request.onupgradeneeded = function (evt) {
handleUpgradeNeeded(evt, index_keys, repair_storage); handleUpgradeNeeded(evt, index_keys, sub_storage_description);
}; };
request.onversionchange = function () { request.onversionchange = function () {
...@@ -292,7 +305,7 @@ ...@@ -292,7 +305,7 @@
IndexStorage2.prototype._runQuery = function (key, value, limit) { IndexStorage2.prototype._runQuery = function (key, value, limit) {
var context = this; var context = this;
return waitForOpenIndexedDB(context._database_name, context._version, return waitForOpenIndexedDB(context._database_name, context._version,
context._index_keys, context._sub_storage, function (db) { context._index_keys, context._sub_storage_description, function (db) {
return waitForTransaction(db, ["index-store"], "readonly", return waitForTransaction(db, ["index-store"], "readonly",
function (tx) { function (tx) {
return context._iterateCursor(tx.objectStore("index-store") return context._iterateCursor(tx.objectStore("index-store")
...@@ -336,7 +349,7 @@ ...@@ -336,7 +349,7 @@
return; return;
} }
return waitForOpenIndexedDB(context._database_name, context._version, return waitForOpenIndexedDB(context._database_name, context._version,
context._index_keys, context._sub_storage, function (db) { context._index_keys, context._sub_storage_description, function (db) {
return waitForTransaction(db, ["index-store"], "readwrite", return waitForTransaction(db, ["index-store"], "readwrite",
function (tx) { function (tx) {
return waitForIDBRequest(tx.objectStore("index-store").put({ return waitForIDBRequest(tx.objectStore("index-store").put({
...@@ -368,7 +381,7 @@ ...@@ -368,7 +381,7 @@
return context._sub_storage.remove(id) return context._sub_storage.remove(id)
.push(function () { .push(function () {
return waitForOpenIndexedDB(context._database_name, context._version, return waitForOpenIndexedDB(context._database_name, context._version,
context._index_keys, context._sub_storage, function (db) { context._index_keys, context._sub_storage_description, function (db) {
return waitForTransaction(db, ["index-store"], "readwrite", return waitForTransaction(db, ["index-store"], "readwrite",
function (tx) { function (tx) {
return waitForIDBRequest(tx.objectStore("index-store") return waitForIDBRequest(tx.objectStore("index-store")
......
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
module("indexStorage2.buildQuery", { module("indexStorage2.buildQuery", {
setup: function () { setup: function () {
DummyStorage3.prototype.hasCapacity = function (name) { DummyStorage3.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'include'); return (name === 'list') || (name === 'include') || (name === 'select');
}; };
DummyStorage3.prototype.buildQuery = function () { DummyStorage3.prototype.buildQuery = function () {
return []; return [];
...@@ -256,7 +256,7 @@ ...@@ -256,7 +256,7 @@
}); });
test("Sub-storage handles empty options", function () { test("Sub-storage handles empty options", function () {
var context = this; var context = this, call_count = 0;
context.jio = jIO.createJIO({ context.jio = jIO.createJIO({
type: "index2", type: "index2",
database: "index2_test", database: "index2_test",
...@@ -273,6 +273,10 @@ ...@@ -273,6 +273,10 @@
}; };
DummyStorage3.prototype.buildQuery = function (options) { DummyStorage3.prototype.buildQuery = function (options) {
call_count += 1;
if (call_count === 1) {
return [];
}
if (options.include_docs !== true) { if (options.include_docs !== true) {
return [ return [
{id: "2", value: {}}, {id: "2", value: {}},
...@@ -307,7 +311,7 @@ ...@@ -307,7 +311,7 @@
}); });
test("Sub storage capacities are used by default", function () { test("Sub storage capacities are used by default", function () {
var context = this; var context = this, kemp = 0;
context.jio = jIO.createJIO({ context.jio = jIO.createJIO({
type: "index2", type: "index2",
database: "index2_test", database: "index2_test",
...@@ -329,6 +333,10 @@ ...@@ -329,6 +333,10 @@
}; };
DummyStorage3.prototype.buildQuery = function (options) { DummyStorage3.prototype.buildQuery = function (options) {
kemp += 1;
if (kemp === 1) {
return [];
}
if (options.include_docs === true) { if (options.include_docs === true) {
return []; return [];
} }
...@@ -488,7 +496,7 @@ ...@@ -488,7 +496,7 @@
}); });
}); });
test("Repair on storage without include_docs support", function () { test("Use existing data to build Index", function () {
var context = this, fake_data; var context = this, fake_data;
context.jio = jIO.createJIO({ context.jio = jIO.createJIO({
type: "index2", type: "index2",
...@@ -499,7 +507,7 @@ ...@@ -499,7 +507,7 @@
} }
}); });
stop(); stop();
expect(3); expect(2);
fake_data = { fake_data = {
"1": {a: "id54", b: 2, c: "night"}, "1": {a: "id54", b: 2, c: "night"},
...@@ -508,7 +516,7 @@ ...@@ -508,7 +516,7 @@
}; };
DummyStorage3.prototype.hasCapacity = function (name) { DummyStorage3.prototype.hasCapacity = function (name) {
return name === 'list'; return (name === 'list') || (name === 'select');
}; };
DummyStorage3.prototype.put = function (id, value) { DummyStorage3.prototype.put = function (id, value) {
fake_data[id] = value; fake_data[id] = value;
...@@ -517,60 +525,9 @@ ...@@ -517,60 +525,9 @@
DummyStorage3.prototype.get = function (id) { DummyStorage3.prototype.get = function (id) {
return fake_data[id]; return fake_data[id];
}; };
DummyStorage3.prototype.buildQuery = function (options) { DummyStorage3.prototype.buildQuery = function () {
deepEqual(options, {});
var keys = Object.keys(fake_data); var keys = Object.keys(fake_data);
return keys.map(function (v) { return {id: v, value: {}}; }); return keys.map(function (v) { return {id: v, value: {id: v}}; });
};
RSVP.all([
context.jio.put("3", {a: "ab43", b: 9, c: "absorb"}),
context.jio.put("5", {a: "gu31", b: 5, c: "control"}),
context.jio.put("7", {a: "zf76", b: 3, c: "rules"}),
context.jio.put("6", {a: "cc92", b: 6, c: "afraid"})
])
.then(function () {
return context.jio.allDocs({query: 'c:"control"'});
})
.then(function (result) {
equal(result.data.total_rows, 2);
deepEqual(result.data.rows.sort(idCompare), [{id: "5", value: {}},
{id: "9", value: {}}]);
})
.fail(function (error) {
console.log(error);
})
.always(function () {
start();
});
});
test("Repair on storage with include_docs support", function () {
var context = this, fake_data;
context.jio = jIO.createJIO({
type: "index2",
database: "index2_test",
index_keys: ["a", "c"],
sub_storage: {
type: "dummystorage3"
}
});
stop();
expect(3);
fake_data = [
{id: "1", doc: {a: "id54", b: 2, c: "night"}},
{id: "4", doc: {a: "vn92", b: 7, c: "matter"}},
{id: "9", doc: {a: "ru23", b: 3, c: "control"}}
];
DummyStorage3.prototype.put = function (id, value) {
fake_data.push({id: id, doc: value});
return id;
};
DummyStorage3.prototype.buildQuery = function (options) {
deepEqual(options, {include_docs: true});
return fake_data;
}; };
RSVP.all([ RSVP.all([
...@@ -694,18 +651,23 @@ ...@@ -694,18 +651,23 @@
expect(8); expect(8);
dummy_data = { dummy_data = {
"32": {id: "32", doc: {"a": "3", "b": "2", "c": "inverse"}}, "32": {id: "32", doc: {"a": "3", "b": "2", "c": "inverse"},
"5": {id: "5", doc: {"a": "6", "b": "2", "c": "strong"}}, value: {"a": "3", "b": "2", "c": "inverse"}},
"14": {id: "14", doc: {"a": "67", "b": "3", "c": "disolve"}} "5": {id: "5", doc: {"a": "6", "b": "2", "c": "strong"},
value: {"a": "6", "b": "2", "c": "strong"}},
"14": {id: "14", doc: {"a": "67", "b": "3", "c": "disolve"},
value: {"a": "67", "b": "3", "c": "disolve"}}
}; };
DummyStorage3.prototype.put = function (id, value) { DummyStorage3.prototype.put = function (id, value) {
dummy_data[id] = {id: id, doc: value}; dummy_data[id] = {id: id, doc: value, value: value};
return id; return id;
}; };
DummyStorage3.prototype.get = function (id) {
return dummy_data[id].doc;
};
DummyStorage3.prototype.hasCapacity = function (name) { DummyStorage3.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'include'); return (name === 'list') || (name === 'include') || (name === 'select');
}; };
DummyStorage3.prototype.buildQuery = function () { DummyStorage3.prototype.buildQuery = function () {
...@@ -802,6 +764,31 @@ ...@@ -802,6 +764,31 @@
}); });
}); });
test("Repair fails", function () {
var context = this;
context.jio = jIO.createJIO({
type: "index2",
database: "index2_test",
index_keys: ["a", "c"],
sub_storage: {
type: "dummystorage3"
}
});
stop();
expect(1);
DummyStorage3.prototype.buildQuery = undefined;
context.jio.allDocs({query: 'c: "control"'})
.fail(function (error) {
equal(error.message, "Version change transaction was aborted in" +
" upgradeneeded event handler.");
})
.always(function () {
start();
});
});
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// IndexStorage2.getAttachment // IndexStorage2.getAttachment
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -948,7 +935,7 @@ ...@@ -948,7 +935,7 @@
}; };
DummyStorage3.prototype.hasCapacity = function (name) { DummyStorage3.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'include'); return (name === 'list') || (name === 'include') || (name === 'select');
}; };
DummyStorage3.prototype.buildQuery = function () { DummyStorage3.prototype.buildQuery = function () {
...@@ -1040,7 +1027,7 @@ ...@@ -1040,7 +1027,7 @@
}; };
DummyStorage3.prototype.hasCapacity = function (name) { DummyStorage3.prototype.hasCapacity = function (name) {
return (name === 'list') || (name === 'include'); return (name === 'list') || (name === 'include') || (name === 'select');
}; };
DummyStorage3.prototype.buildQuery = function () { DummyStorage3.prototype.buildQuery = function () {
......
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