Commit 99ef16cd authored by Vincent Bechu's avatar Vincent Bechu

indexeddbstorage: use callback instead promise

this fix indexeddb usage in firefox service worker, which closes transaction automatically
parent 754e5df9
...@@ -148,9 +148,7 @@ ...@@ -148,9 +148,7 @@
return tx; return tx;
} }
function handleCursor(request, callback) { function handleCursor(request, callback, resolve, reject) {
function resolver(resolve, reject) {
// Open DB //
request.onerror = function (error) { request.onerror = function (error) {
if (request.transaction) { if (request.transaction) {
request.transaction.abort(); request.transaction.abort();
...@@ -175,9 +173,6 @@ ...@@ -175,9 +173,6 @@
} }
}; };
} }
// XXX Canceller???
return new RSVP.Promise(resolver);
}
IndexedDBStorage.prototype.buildQuery = function (options) { IndexedDBStorage.prototype.buildQuery = function (options) {
var result_list = []; var result_list = [];
...@@ -198,40 +193,45 @@ ...@@ -198,40 +193,45 @@
} }
return openIndexedDB(this) return openIndexedDB(this)
.push(function (db) { .push(function (db) {
return new RSVP.Promise(function (resolve, reject) {
var tx = openTransaction(db, ["metadata"], "readonly"); var tx = openTransaction(db, ["metadata"], "readonly");
if (options.include_docs === true) { if (options.include_docs === true) {
return handleCursor(tx.objectStore("metadata").index("_id") handleCursor(tx.objectStore("metadata").index("_id").openCursor(),
.openCursor(), pushIncludedMetadata); pushIncludedMetadata, resolve, reject);
} else {
handleCursor(tx.objectStore("metadata").index("_id")
.openKeyCursor(), pushMetadata, resolve, reject);
} }
return handleCursor(tx.objectStore("metadata").index("_id") });
.openKeyCursor(), pushMetadata);
}) })
.push(function () { .push(function () {
return result_list; return result_list;
}); });
}; };
function handleGet(request) { function handleGet(request, resolve, reject) {
function resolver(resolve, reject) {
request.onerror = reject; request.onerror = reject;
request.onsuccess = function () { request.onsuccess = function () {
if (request.result) { if (request.result) {
resolve(request.result); resolve(request.result);
} } else {
// XXX How to get ID // XXX How to get ID
reject(new jIO.util.jIOError("Cannot find document", 404)); reject(new jIO.util.jIOError("Cannot find document", 404));
};
} }
return new RSVP.Promise(resolver); };
} }
IndexedDBStorage.prototype.get = function (id) { IndexedDBStorage.prototype.get = function (id) {
return openIndexedDB(this) return openIndexedDB(this)
.push(function (db) { .push(function (db) {
var transaction = openTransaction(db, ["metadata"], return new RSVP.Promise(function (resolve, reject) {
"readonly"); var transaction = openTransaction(db, ["metadata"], "readonly");
return handleGet(transaction.objectStore("metadata").get(id)); handleGet(
transaction.objectStore("metadata").get(id),
resolve,
reject
);
});
}) })
.push(function (result) { .push(function (result) {
return result.doc; return result.doc;
...@@ -247,37 +247,51 @@ ...@@ -247,37 +247,51 @@
return openIndexedDB(this) return openIndexedDB(this)
.push(function (db) { .push(function (db) {
return new RSVP.Promise(function (resolve, reject) {
var transaction = openTransaction(db, ["metadata", "attachment"], var transaction = openTransaction(db, ["metadata", "attachment"],
"readonly"); "readonly");
return RSVP.all([ function getAttachments() {
handleGet(transaction.objectStore("metadata").get(id)), handleCursor(
handleCursor(transaction.objectStore("attachment").index("_id") transaction.objectStore("attachment").index("_id")
.openCursor(IDBKeyRange.only(id)), addEntry) .openCursor(IDBKeyRange.only(id)),
]); addEntry,
resolve,
reject
);
}
handleGet(
transaction.objectStore("metadata").get(id),
getAttachments,
reject
);
});
}) })
.push(function () { .push(function () {
return attachment_dict; return attachment_dict;
}); });
}; };
function handleRequest(request) { function handleRequest(request, resolve, reject) {
function resolver(resolve, reject) {
request.onerror = reject; request.onerror = reject;
request.onsuccess = function () { request.onsuccess = function () {
resolve(request.result); resolve(request.result);
}; };
} }
return new RSVP.Promise(resolver);
}
IndexedDBStorage.prototype.put = function (id, metadata) { IndexedDBStorage.prototype.put = function (id, metadata) {
return openIndexedDB(this) return openIndexedDB(this)
.push(function (db) { .push(function (db) {
return new RSVP.Promise(function (resolve, reject) {
var transaction = openTransaction(db, ["metadata"], "readwrite"); var transaction = openTransaction(db, ["metadata"], "readwrite");
return handleRequest(transaction.objectStore("metadata").put({ handleRequest(
transaction.objectStore("metadata").put({
"_id": id, "_id": id,
"doc": metadata "doc": metadata
})); }),
resolve,
reject
);
});
}); });
}; };
...@@ -286,19 +300,38 @@ ...@@ -286,19 +300,38 @@
} }
IndexedDBStorage.prototype.remove = function (id) { IndexedDBStorage.prototype.remove = function (id) {
var resolved_amount = 0;
return openIndexedDB(this) return openIndexedDB(this)
.push(function (db) { .push(function (db) {
return new RSVP.Promise(function (resolve, reject) {
function resolver() {
if (resolved_amount < 2) {
resolved_amount += 1;
} else {
resolve();
}
}
var transaction = openTransaction(db, ["metadata", "attachment", var transaction = openTransaction(db, ["metadata", "attachment",
"blob"], "readwrite"); "blob"], "readwrite");
return RSVP.all([ handleRequest(
handleRequest(transaction transaction.objectStore("metadata")["delete"](id),
.objectStore("metadata")["delete"](id)), resolver,
reject
);
// XXX Why not possible to delete with KeyCursor? // XXX Why not possible to delete with KeyCursor?
handleCursor(transaction.objectStore("attachment").index("_id") handleCursor(transaction.objectStore("attachment").index("_id")
.openCursor(IDBKeyRange.only(id)), deleteEntry), .openCursor(IDBKeyRange.only(id)),
deleteEntry,
resolver,
reject
);
handleCursor(transaction.objectStore("blob").index("_id") handleCursor(transaction.objectStore("blob").index("_id")
.openCursor(IDBKeyRange.only(id)), deleteEntry) .openCursor(IDBKeyRange.only(id)),
]); deleteEntry,
resolver,
reject
);
});
}); });
}; };
...@@ -312,48 +345,64 @@ ...@@ -312,48 +345,64 @@
} }
return openIndexedDB(this) return openIndexedDB(this)
.push(function (db) { .push(function (db) {
transaction = openTransaction(db, ["attachment", "blob"], "readonly"); return new RSVP.Promise(function (resolve, reject) {
// XXX Should raise if key is not good transaction = openTransaction(
return handleGet(transaction.objectStore("attachment") db,
.get(buildKeyPath([id, name]))); ["attachment", "blob"],
}) "readonly"
.push(function (attachment) { );
function getBlob(attachment) {
var total_length = attachment.info.length, var total_length = attachment.info.length,
i, result_list = [],
promise_list = [],
store = transaction.objectStore("blob"), store = transaction.objectStore("blob"),
start_index, start_index,
end_index; end_index;
type = attachment.info.content_type; type = attachment.info.content_type;
start = options.start || 0; start = options.start || 0;
end = options.end || total_length; end = options.end || total_length;
if (end > total_length) { if (end > total_length) {
end = total_length; end = total_length;
} }
if (start < 0 || end < 0) { if (start < 0 || end < 0) {
throw new jIO.util.jIOError("_start and _end must be positive", throw new jIO.util.jIOError(
400); "_start and _end must be positive",
400
);
} }
if (start > end) { if (start > end) {
throw new jIO.util.jIOError("_start is greater than _end", throw new jIO.util.jIOError("_start is greater than _end",
400); 400);
} }
start_index = Math.floor(start / UNITE); start_index = Math.floor(start / UNITE);
end_index = Math.floor(end / UNITE); end_index = Math.floor(end / UNITE) - 1;
if (end % UNITE === 0) { if (end % UNITE === 0) {
end_index -= 1; end_index -= 1;
} }
function resolver(result) {
for (i = start_index; i <= end_index; i += 1) { result_list.push(result);
promise_list.push( resolve(result_list);
handleGet(store.get(buildKeyPath([id, }
name, i]))) function getPart(i) {
return function (result) {
if (result) {
result_list.push(result);
}
i += 1;
handleGet(store.get(buildKeyPath([id, name, i])),
(i <= end_index) ? getPart(i) : resolver,
reject
); );
};
} }
return RSVP.all(promise_list); getPart(start_index - 1)();
}
// XXX Should raise if key is not good
handleGet(transaction.objectStore("attachment")
.get(buildKeyPath([id, name])),
getBlob,
reject
);
});
}) })
.push(function (result_list) { .push(function (result_list) {
var array_buffer_list = [], var array_buffer_list = [],
...@@ -374,19 +423,24 @@ ...@@ -374,19 +423,24 @@
}); });
}; };
function removeAttachment(transaction, id, name) { function removeAttachment(transaction, id, name, resolve, reject) {
return RSVP.all([
// XXX How to get the right attachment // XXX How to get the right attachment
handleRequest(transaction.objectStore("attachment")["delete"]( function deleteContent() {
handleCursor(
transaction.objectStore("blob").index("_id_attachment")
.openCursor(IDBKeyRange.only([id, name])),
deleteEntry,
resolve,
reject
);
}
handleRequest(
transaction.objectStore("attachment")["delete"](
buildKeyPath([id, name]) buildKeyPath([id, name])
)), ),
handleCursor(transaction.objectStore("blob").index("_id_attachment") deleteContent,
.openCursor(IDBKeyRange.only( reject
[id, name] );
)),
deleteEntry
)
]);
} }
IndexedDBStorage.prototype.putAttachment = function (id, name, blob) { IndexedDBStorage.prototype.putAttachment = function (id, name, blob) {
...@@ -414,12 +468,29 @@ ...@@ -414,12 +468,29 @@
// Remove previous attachment // Remove previous attachment
transaction = openTransaction(db, ["attachment", "blob"], "readwrite"); transaction = openTransaction(db, ["attachment", "blob"], "readwrite");
return removeAttachment(transaction, id, name); return new RSVP.Promise(function (resolve, reject) {
}) function write() {
.push(function () { var len = blob_part.length - 1,
attachment_store = transaction.objectStore("attachment"),
var promise_list = [ blob_store = transaction.objectStore("blob");
handleRequest(transaction.objectStore("attachment").put({ function putBlobPart(i) {
return function () {
i += 1;
handleRequest(
blob_store.put({
"_key_path": buildKeyPath([id, name, i]),
"_id" : id,
"_attachment" : name,
"_part" : i,
"blob": blob_part[i]
}),
(i < len) ? putBlobPart(i) : resolve,
reject
);
};
}
handleRequest(
attachment_store.put({
"_key_path": buildKeyPath([id, name]), "_key_path": buildKeyPath([id, name]),
"_id": id, "_id": id,
"_attachment": name, "_attachment": name,
...@@ -427,25 +498,13 @@ ...@@ -427,25 +498,13 @@
"content_type": blob.type, "content_type": blob.type,
"length": blob.size "length": blob.size
} }
})) }),
], putBlobPart(-1),
len = blob_part.length, reject
blob_store = transaction.objectStore("blob"),
i;
for (i = 0; i < len; i += 1) {
promise_list.push(
handleRequest(blob_store.put({
"_key_path": buildKeyPath([id, name,
i]),
"_id" : id,
"_attachment" : name,
"_part" : i,
"blob": blob_part[i]
}))
); );
} }
// Store all new data removeAttachment(transaction, id, name, write, reject);
return RSVP.all(promise_list); });
}); });
}; };
...@@ -454,7 +513,9 @@ ...@@ -454,7 +513,9 @@
.push(function (db) { .push(function (db) {
var transaction = openTransaction(db, ["attachment", "blob"], var transaction = openTransaction(db, ["attachment", "blob"],
"readwrite"); "readwrite");
return removeAttachment(transaction, id, name); return new RSVP.Promise(function (resolve, reject) {
removeAttachment(transaction, id, name, resolve, reject);
});
}); });
}; };
......
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