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,35 +148,30 @@ ...@@ -148,35 +148,30 @@
return tx; return tx;
} }
function handleCursor(request, callback) { function handleCursor(request, callback, resolve, reject) {
function resolver(resolve, reject) { request.onerror = function (error) {
// Open DB // if (request.transaction) {
request.onerror = function (error) { request.transaction.abort();
if (request.transaction) { }
request.transaction.abort(); reject(error);
} };
reject(error);
};
request.onsuccess = function (evt) {
var cursor = evt.target.result;
if (cursor) {
// XXX Wait for result
try {
callback(cursor);
} catch (error) {
reject(error);
}
// continue to next iteration request.onsuccess = function (evt) {
cursor["continue"](); var cursor = evt.target.result;
} else { if (cursor) {
resolve(); // XXX Wait for result
try {
callback(cursor);
} catch (error) {
reject(error);
} }
};
} // continue to next iteration
// XXX Canceller??? cursor["continue"]();
return new RSVP.Promise(resolver); } else {
resolve();
}
};
} }
IndexedDBStorage.prototype.buildQuery = function (options) { IndexedDBStorage.prototype.buildQuery = function (options) {
...@@ -198,40 +193,45 @@ ...@@ -198,40 +193,45 @@
} }
return openIndexedDB(this) return openIndexedDB(this)
.push(function (db) { .push(function (db) {
var tx = openTransaction(db, ["metadata"], "readonly"); return new RSVP.Promise(function (resolve, reject) {
if (options.include_docs === true) { var tx = openTransaction(db, ["metadata"], "readonly");
return handleCursor(tx.objectStore("metadata").index("_id") if (options.include_docs === true) {
.openCursor(), pushIncludedMetadata); handleCursor(tx.objectStore("metadata").index("_id").openCursor(),
} pushIncludedMetadata, resolve, reject);
return handleCursor(tx.objectStore("metadata").index("_id") } else {
.openKeyCursor(), pushMetadata); handleCursor(tx.objectStore("metadata").index("_id")
.openKeyCursor(), pushMetadata, resolve, reject);
}
});
}) })
.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) {
var transaction = openTransaction(db, ["metadata", "attachment"], return new RSVP.Promise(function (resolve, reject) {
"readonly"); var transaction = openTransaction(db, ["metadata", "attachment"],
return RSVP.all([ "readonly");
handleGet(transaction.objectStore("metadata").get(id)), function getAttachments() {
handleCursor(transaction.objectStore("attachment").index("_id") handleCursor(
.openCursor(IDBKeyRange.only(id)), addEntry) transaction.objectStore("attachment").index("_id")
]); .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) {
var transaction = openTransaction(db, ["metadata"], "readwrite"); return new RSVP.Promise(function (resolve, reject) {
return handleRequest(transaction.objectStore("metadata").put({ var transaction = openTransaction(db, ["metadata"], "readwrite");
"_id": id, handleRequest(
"doc": metadata transaction.objectStore("metadata").put({
})); "_id": id,
"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) {
var transaction = openTransaction(db, ["metadata", "attachment", return new RSVP.Promise(function (resolve, reject) {
"blob"], "readwrite"); function resolver() {
return RSVP.all([ if (resolved_amount < 2) {
handleRequest(transaction resolved_amount += 1;
.objectStore("metadata")["delete"](id)), } else {
resolve();
}
}
var transaction = openTransaction(db, ["metadata", "attachment",
"blob"], "readwrite");
handleRequest(
transaction.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) {
var total_length = attachment.info.length,
i,
promise_list = [],
store = transaction.objectStore("blob"),
start_index,
end_index;
type = attachment.info.content_type;
start = options.start || 0;
end = options.end || total_length;
if (end > total_length) {
end = total_length;
}
if (start < 0 || end < 0) {
throw new jIO.util.jIOError("_start and _end must be positive",
400);
}
if (start > end) {
throw new jIO.util.jIOError("_start is greater than _end",
400);
}
start_index = Math.floor(start / UNITE);
end_index = Math.floor(end / UNITE);
if (end % UNITE === 0) {
end_index -= 1;
}
for (i = start_index; i <= end_index; i += 1) {
promise_list.push(
handleGet(store.get(buildKeyPath([id,
name, i])))
); );
} function getBlob(attachment) {
return RSVP.all(promise_list); var total_length = attachment.info.length,
result_list = [],
store = transaction.objectStore("blob"),
start_index,
end_index;
type = attachment.info.content_type;
start = options.start || 0;
end = options.end || total_length;
if (end > total_length) {
end = total_length;
}
if (start < 0 || end < 0) {
throw new jIO.util.jIOError(
"_start and _end must be positive",
400
);
}
if (start > end) {
throw new jIO.util.jIOError("_start is greater than _end",
400);
}
start_index = Math.floor(start / UNITE);
end_index = Math.floor(end / UNITE) - 1;
if (end % UNITE === 0) {
end_index -= 1;
}
function resolver(result) {
result_list.push(result);
resolve(result_list);
}
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
);
};
}
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,38 +468,43 @@ ...@@ -414,38 +468,43 @@
// 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) {
"_key_path": buildKeyPath([id, name]), return function () {
"_id": id, i += 1;
"_attachment": name, handleRequest(
"info": { blob_store.put({
"content_type": blob.type, "_key_path": buildKeyPath([id, name, i]),
"length": blob.size "_id" : id,
} "_attachment" : name,
})) "_part" : i,
], "blob": blob_part[i]
len = blob_part.length, }),
blob_store = transaction.objectStore("blob"), (i < len) ? putBlobPart(i) : resolve,
i; reject
for (i = 0; i < len; i += 1) { );
promise_list.push( };
handleRequest(blob_store.put({ }
"_key_path": buildKeyPath([id, name, handleRequest(
i]), attachment_store.put({
"_id" : id, "_key_path": buildKeyPath([id, name]),
"_attachment" : name, "_id": id,
"_part" : i, "_attachment": name,
"blob": blob_part[i] "info": {
})) "content_type": blob.type,
); "length": blob.size
} }
// Store all new data }),
return RSVP.all(promise_list); putBlobPart(-1),
reject
);
}
removeAttachment(transaction, id, name, write, reject);
});
}); });
}; };
...@@ -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