- From: Andrei Popescu <andreip@google.com>
- Date: Wed, 4 Aug 2010 17:26:23 +0100
- To: Jeremy Orlow <jorlow@chromium.org>
- Cc: public-webapps WG <public-webapps@w3.org>
On Wed, Aug 4, 2010 at 4:42 PM, Jeremy Orlow <jorlow@chromium.org> wrote: > 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. > I think it's only allowed as long as the object store in question is in the scope of this other transaction. > 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? As currently specced, I think that would indeed start 5 separate transactions. But couldn't you save the object store in a variable before the loop? > 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? > I think simply calling window.myObjectStore.get() would not create a transaction. I think it would just throw? myDB.objectStore().get() would create a transaction. > 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. That's right, it seems like a problem to me. > 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? > Well, what's wrong with what's specced today: - you can only call get/put/etc in the context of a transaction. If you don't, they'll throw. - "in the context of a transaction" means in a transaction callback or after you created an implicit transaction and until control returns to the main browser event loop. > 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? > Right. But IDBDatabase::objectStore() takes a mode parameter. You can pass READ_WRITE if you want. > 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? Not sure, perhaps we need better wording in the spec to explain how they work? Thanks, Andrei
Received on Wednesday, 4 August 2010 16:26:53 UTC