[IndexedDB] Implicit transactions

In the IndexedDB spec, there are two ways to create a transaction.  One is
explicit (by calling IDBDatabase.transaction()) and one is implicit (for
example, by calling IDBDatabase.objectStore.get("someKey")).  I have
questions about the latter, but before bringing these up, I think it might
be best to give a bit of background (as I understand it) to make sure we're
all on the same page:


*Belief 1:*
No matter how the transaction is started, any subsequent calls done within
an IDBTransactionEvent (which is the event fired for almost every
IDBRequest.onsuccess call since almost all of them are for operations done
within the context of a transaction) will continue running in the same
transaction.  So, for example, the following code will atomically increment
a counter:

myDB.transaction().onsuccess(function() {
    myDB.objectStore("someObjectStore").get("counter").onsuccess(function()
{
        myDB.objectStore("someObjectStore").put("counter", event.result +
1);
    });
});


*Belief 2:*
Let's say I ran the following code:

myDB.transaction().onsuccess(function() { window.myObjectStore =
myDB.objectStore("someObjectStore"); /* do some other work */ });

And then at any point later in the program (after that first transaction had
committed) I could do the following:

myDB.transaction().onsuccess(function() { window.myObjectStore.get("some
value").onsuccess(...); });

Even though myObjectStore was originally fetched during some other
transaction, it's quite clear that I'm accessing values from that object
store in this new transaction's context, and thus that's exactly what
happens and this is allowed.


*Implicitly created transactions:*
At a high level, the intent is for
IDBDatabase.objectStore.get("someKey").onsuccess(...); to "just work", even
when not called in an IDBTransactionEvent handler.  But what happens if I
run the following code (outside of an IDBTransactionEvent handler):

for (var i=0; i<5; ++i)
    myDB.objectStore("someObjectStore").get("someKey").onsuccess(...);

Do we want that to create 5 separate transactions or 5 requests within the
same transaction?

And what if we run my earlier example (that stored an object store to
window.myObjectStore within a transaction we started explicitly) and then
run the following code (outside of an IDBTransactionEventHandler):

window.myObjectStore.get("someKey").onsuccess(...);
myDB.objectStore("someObjectStore").get("someKey").onsuccess(...)

Should both be legal?  Will this create one or two transactions?


*Speccing such transactions:*
After thinking about this, I only see a couple options for how to spec
implicitly created transactions:

"When an operation that needs to be done in a transaction (i.e. anything
that touches data) is done outside of an IDBTransactionEvent handler..."
1) "that operation will be done in its own, newly created transaction."
2) "if there already exists an implicitly created transaction for that
objectStore, it'll be done in that transaction.  Otherwise a new one will be
created."
3) "if there already exists _any_ transaction with access to that
objectStore, it'll be done in that transaction.  Otherwise a new one will be
created."

2 seems like it'd match the users intention in a lot of cases, but its
biggest problem is that it's non-deterministic.  If you do one .get() and
then set a time out and do another, you don't know whether they'll be in the
same transaction or not.  3 seems to have the same problem except it's even
less predictable.  So, but process of elimination, it seems as though 1 is
our only option in terms of how to spec this.  Or am I missing something?


*Read-only by default too?*
Another somewhat related question: should implicitly created transactions be
read-only (which is the default for explicitly created ones)?  If so, that
means that we expect the following to fail:

myDB.objectStore("someObjectStore").get("counter").onsuccess(function() {
    myDB.objectStore("someObjectStore").put("counter", event.result + 1);
});

Unfortunately, it seems as though a lot of use cases for implicitly created
transactions would involve more than just reads.  But if we spec that to
succeed, then we're lowering concurrency and making things inconsistent with
the default for IDBDatabase.transaction(), right?


*Conclusion:*
Am I missing something here?  Or will properly speccing implicitly created
transactions lead to them being nearly useless for the simple use cases we
were trying to make simpler to begin with?

J

Received on Wednesday, 4 August 2010 15:43:42 UTC