Commit 05349435 authored by Yaxel Perez's avatar Yaxel Perez

fixed concurrency issues so that all tests pass

parent 4c66f034
...@@ -330,10 +330,6 @@ ...@@ -330,10 +330,6 @@
}); });
}; };
JioProxyStorage.prototype.list = function () {
return this.__storage.list.apply(this.__storage, arguments);
};
declareMethod(JioProxyStorage, 'putAttachment', function (argument_list, declareMethod(JioProxyStorage, 'putAttachment', function (argument_list,
storage, storage,
method_name) { method_name) {
...@@ -475,11 +471,6 @@ ...@@ -475,11 +471,6 @@
options = {}; options = {};
} }
return ensurePushableQueue(function () { return ensurePushableQueue(function () {
// this will fail with an unhelpful errror message if context does not
// have the "query" capacity.
// possible fixes:
// - Catch errors thrown by hasCapacity everywhere all the time
// - Refactor hasCapacity to return false instead of raising an error
if (context.hasCapacity("list") && if (context.hasCapacity("list") &&
((options.query === undefined) || context.hasCapacity("query")) && ((options.query === undefined) || context.hasCapacity("query")) &&
((options.sort_on === undefined) || context.hasCapacity("sort")) && ((options.sort_on === undefined) || context.hasCapacity("sort")) &&
......
/*global define, jIO */ /*global define, jIO, RSVP */
/*jslint nomen: true*/ /*jslint nomen: true*/
(function (jIO) { (function (jIO) {
// (function (jIO, RSVP) {
"use strict"; "use strict";
function randomId() {
// https://gist.github.com/gordonbrander/2230317
return '_' + Math.random().toString(36).substr(2, 9);
}
function ListStorage(spec) { function ListStorage(spec) {
this._sub_storage = jIO.createJIO(spec.sub_storage); this._sub_storage = jIO.createJIO(spec.sub_storage);
this._signature_storage = jIO.createJIO({ this._index_storage = jIO.createJIO(spec.index_storage);
"type": "indexeddb", this._index_initialized = false;
"database": randomId() this._index_tmp = []; // temporary array to put ids
}); this._index_removed_tmp = []; // temp array to put removed ids
} }
ListStorage.prototype.list = function () { ListStorage.prototype.buildQuery = function () {
// lazily initialize the list in _signature_storage return this.getIndex();
var ctx = this; };
return this._signature_storage.get('_').then(function (list) {
return list; ListStorage.prototype.hasCapacity = function (name) {
}).fail(function () { if (name === 'list') {
return ctx._signature_storage.put('_', []).then(function () { return true;
return []; }
return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments);
};
ListStorage.prototype.getIndex = function () {
// in brief:
// pull all ids from _index_tmp and put them in the _index_storage
// and remove ids from _index_removed_tmp
// and then return the new '_' entry
var ctx = this,
tmp = this._index_tmp,
removed_tmp = this._index_removed_tmp;
ctx._index_tmp = [];
ctx._index_removed_tmp = [];
if (!ctx._index_initialized) {
ctx._index_initialized = true;
tmp = tmp.filter(function (id) {
return removed_tmp.indexOf(id) === -1;
});
return this._index_storage.put('_', tmp)
.then(function () {
return tmp;
});
}
return ctx._index_storage.get('_').then(function (index) {
var newIndex = index.concat(tmp);
newIndex = newIndex.filter(function (id) {
return removed_tmp.indexOf(id) === -1;
}); });
return ctx._index_storage.put('_', newIndex)
.then(function () {
return newIndex;
});
}); });
}; };
...@@ -33,12 +60,8 @@ ...@@ -33,12 +60,8 @@
var ctx = this; var ctx = this;
return this._sub_storage.post.apply(this._sub_storage, arguments) return this._sub_storage.post.apply(this._sub_storage, arguments)
.then(function (id) { .then(function (id) {
return ctx.list().then(function (list) { ctx._index_tmp.push(id);
list.push(id); return id;
return ctx._signature_storage.put('_', list).then(function () {
return id;
});
});
}); });
}; };
...@@ -50,12 +73,8 @@ ...@@ -50,12 +73,8 @@
var ctx = this; var ctx = this;
return this._sub_storage.put.apply(this._sub_storage, arguments) return this._sub_storage.put.apply(this._sub_storage, arguments)
.then(function (id) { .then(function (id) {
return ctx.list().then(function (list) { ctx._index_tmp.push(id);
list.push(id); return id;
return ctx._signature_storage.put('_', list).then(function () {
return id;
});
});
}); });
}; };
...@@ -63,14 +82,11 @@ ...@@ -63,14 +82,11 @@
var ctx = this; var ctx = this;
return this._sub_storage.remove.apply(this._sub_storage, arguments) return this._sub_storage.remove.apply(this._sub_storage, arguments)
.then(function (id) { .then(function (id) {
return ctx.list().then(function (list) { ctx._index_removed_tmp.push(id);
list = list.filter(function (x) { return id !== x; }); return id;
return ctx._signature_storage.put('_', list).then(function () {
return id;
});
});
}); });
}; };
jIO.addStorage("list", ListStorage); jIO.addStorage("list", ListStorage);
}(jIO)); }(jIO));
// }(jIO, RSVP));
...@@ -29,8 +29,11 @@ ...@@ -29,8 +29,11 @@
this._sub_storage = jIO.createJIO(spec.sub_storage); this._sub_storage = jIO.createJIO(spec.sub_storage);
} }
NoCapacityStorage.prototype.hasCapacity = function () { NoCapacityStorage.prototype.hasCapacity = function (name) {
return false; if (name === "query") {
return false;
}
return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments);
}; };
NoCapacityStorage.prototype.get = function () { NoCapacityStorage.prototype.get = function () {
......
...@@ -9,12 +9,80 @@ ...@@ -9,12 +9,80 @@
type: "list", type: "list",
sub_storage: { sub_storage: {
type: "memory" type: "memory"
},
index_storage: {
type: "memory"
} }
}); });
QUnit.expect(0); QUnit.expect(0);
}); });
// NOTE: list method is implicitly tested in the following two methods QUnit.test("check concurrent write", function () {
QUnit.stop();
QUnit.expect(12);
var i,
promise_list = [],
storage = jIO.createJIO({
type: "list",
// This storage will store the document IDs
index_storage: {
type: "memory"
},
// This storage will store the documents
sub_storage: {
type: "nocapacity",
sub_storage: {
type: "memory"
}
}
});
// Create many document in parallel
for (i = 0; i < 10; i += 1) {
promise_list.push(storage.put('foo' + i, {bar: i}));
}
return RSVP.all(promise_list)
.then(function () {
// The list of document can be retrieved
return storage.allDocs();
})
.then(function (result) {
QUnit.equal(result.data.total_rows, 10);
// Every document can be retrieved too
promise_list = [];
for (i = 0; i < 10; i += 1) {
promise_list.push(storage.get('foo' + i));
}
return RSVP.all(promise_list);
})
.then(function (result_list) {
for (i = 0; i < 10; i += 1) {
QUnit.deepEqual(result_list[i], {bar: i});
}
// Remove all documents
promise_list = [];
for (i = 0; i < 10; i += 1) {
promise_list.push(storage.remove('foo' + i));
}
return RSVP.all(promise_list);
})
.then(function () {
// The list of document must be empty
return storage.allDocs();
})
.then(function (result) {
QUnit.equal(result.data.total_rows, 0);
})
.fail(function (error) {
console.error(error);
throw error;
})
.always(function () {
QUnit.start();
});
});
QUnit.test('post method correctly records ids', function (assert) { QUnit.test('post method correctly records ids', function (assert) {
QUnit.stop(); QUnit.stop();
...@@ -22,21 +90,31 @@ ...@@ -22,21 +90,31 @@
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: 'list', type: 'list',
index_storage: {
type: "memory",
},
sub_storage: { sub_storage: {
type: 'uuid', type: 'uuid',
sub_storage: { sub_storage: {
type: 'memory' type: 'memory'
} }
} }
}); }),
promise_list = [],
i = 0;
jio.post({}).then(function (id1) { for (i = 0; i < 10; i += 1) {
jio.post({}).then(function (id2) { promise_list.push(jio.post(i));
jio.list().then(function (l) { }
QUnit.start();
assert.deepEqual(l, [id1, id2]); RSVP.all(promise_list).then(function (ids) {
}); var x = jio.allDocs();
}); x.then(function (res) {
return res.data.rows;
}).then(function (rows) {
QUnit.start();
assert.deepEqual(rows, ids);
}).fail(console.error);
}).fail(console.error); }).fail(console.error);
}); });
...@@ -46,21 +124,31 @@ ...@@ -46,21 +124,31 @@
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: 'list', type: 'list',
index_storage: {
type: "memory",
},
sub_storage: { sub_storage: {
type: 'uuid', type: 'uuid',
sub_storage: { sub_storage: {
type: 'memory' type: 'memory'
} }
} }
}); }),
promise_list = [],
i = 0;
jio.put('test', {}).then(function (id1) { for (i = 0; i < 10; i += 1) {
jio.put('test2', {}).then(function (id2) { promise_list.push(jio.put(i.toString(), {'test': i}));
jio.list().then(function (l) { }
QUnit.start();
assert.deepEqual(l, [id1, id2]); RSVP.all(promise_list).then(function (ids) {
}); var x = jio.allDocs();
}); x.then(function (res) {
return res.data.rows;
}).then(function (rows) {
QUnit.start();
assert.deepEqual(rows, ids);
}).fail(console.error);
}).fail(console.error); }).fail(console.error);
}); });
...@@ -70,22 +158,38 @@ ...@@ -70,22 +158,38 @@
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: 'list', type: 'list',
index_storage: {
type: "memory",
},
sub_storage: { sub_storage: {
type: 'uuid', type: 'uuid',
sub_storage: { sub_storage: {
type: 'memory' type: 'memory'
} }
} }
}); }),
promise_list = [],
i = 0;
jio.put('test', {}).then(function () { for (i = 0; i < 10; i += 1) {
jio.put('test2', {}).then(function () { promise_list.push(jio.put(i.toString(), {'test': i}));
jio.remove('test').then(function () { }
jio.list().then(function (l2) {
QUnit.start(); RSVP.all(promise_list).then(function (ids) {
assert.deepEqual(l2, ['test2']); var removal_promises = [];
}); for (i = 0; i < 10; i += 1) {
}); removal_promises.push(jio.remove(ids[i]));
}
RSVP.all(removal_promises).then(function () {
return jio.allDocs();
}).then(function (res) {
return res.data.rows;
}).then(function (all) {
QUnit.start();
assert.deepEqual(all, []);
}).fail(function (err) {
console.error(err);
QUnit.start();
}); });
}).fail(console.error); }).fail(console.error);
}); });
......
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