IndexedDB: ambiguity around createIndex order-of-operations

jsbell and I have been discussing a possible ambiguity in the IndexedDB
spec w.r.t. error handling around createIndex calls.


In particular, createIndex() is supposed to behave somewhat synchronously
in that calling:


> the implementation *must* create a newindex<http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#dfn-index> and
> return an IDBIndex<http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBIndex> object
> representing it.


so that this is reasonable:
objectStore.createIndex('foo',...)
objectStore.put(...)
objectStore.index('foo').get(...)

But at the same time createIndex() behaves somewhat asynchrnously - while
the metadata for the index needs to be there immediately, the actual
indexing data doesn't have to:

In some implementations it's possible for the implementation to
> asynchronously run into problems creating the index after the createIndex
> function has returned. For example in implementations where metadata about
> the newly created index is queued up to be inserted into the database
> asynchronously, or where the implementation might need to ask the user for
> permission for quota reasons. Such implementations *must* still create
> and return an IDBIndex<http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBIndex> object.
> Instead, once the implementation realizes that creating the index has
> failed, it *must* abort the transaction using thesteps for aborting a
> transaction<http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#dfn-steps-for-aborting-a-transaction> using
> the appropriate error as error parameter.


The issue in question is how to handle this:

objectStore.put({"foo": 1, "message": "hello"});
req = objectStore.put({"foo": 1, "message": "goodbye"});
objectStore.createIndex("foo", "foo", {unique: true});    // will fail
asynchronously

The question is, should req's onerror fire or not? Depending on the
implementation, createIndex() could fully create/index the whole 'foo'
index before the put's are serviced, which means by the time the 2nd put()
happens, the index already says that the put is invalid. On the other hand,
if the actual indexing happens later (asynchronously), but in the order
written (i.e. put(), put(), createIndex) then the 2nd put would succeed,
and THEN the index gets created. In either case the transaction is aborted.

>From a developer's perspective, I feel like making the 2nd put() fail is
really confusing, because it seems really strange that a later API call
(createIndex) could make an earlier put() fail - you might remove the
createIndex() to debug the code and then magically it would succeed! On the
other hand, that behavior does allow the creator to preventBubble() to
prevent the failure, which could prevent the transaction from failing.

In either case, I feel like this is a fairly degenerate case and I feel
like we need to optimize this behavior for debugging, since I don't think
normal usage patterns of IndexedDB should be doing this.

Alec

Received on Monday, 13 August 2012 18:16:55 UTC