On Mon, Sep 12, 2011 at 2:37 PM, Israel Hilerio <[email protected]> wrote: > On Monday, September 12, 2011 1:56 PM, Israel Hilerio wrote: >> On Sunday, September 04, 2011 3:33 AM, Jonas Sicking wrote: >> > Hi Everyone, >> > >> > I finally got around to updating the IndexedDB spec to the new version API! >> > Definitely a non-trivial change, so I'd love for people to have a look >> > at it to see if I messed anything up. >> > >> > I decided to go with the name "upgradeneeded" for the event fired when >> > a version upgrade is needed. I'm not terribly happy with the name, but >> > it does feel descriptive. >> > >> > I also went with integers (long long) for the version number. The >> > reason was that I wanted to avoid people passing strings like "1.10" >> > to the API since JS will automatically and silently convert that to >> > the number 1.1. This could lead to confusion since people might think >> > that "1.10" is a higher version than "1.9". >> > >> > >> > There were a few issues that came up during editing, mostly related to >> > edge cases that doesn't matter terribly much: >> > >> > * What to do if multiple different versions are opened at the same time. >> > Consider the following scenario. A database with name "mydb" has >> > version 3. The following two calls happen almost at the same time: >> > >> > req1 = indexedDB.open("mydb", 4); >> > and >> > req2 = indexedDB.open("mydb", 5); >> > >> > It's clear that we should here fire a "upgradeneeded" event on req2 >> > and let it run a VERSION_CHANGE transaction to upgrade the database to >> version 5. >> > There are however two possible things we could do to req1. >> > >> > A) Immediately fail by firing an "error" event on req1. >> > B) Wait for req2 to attempt to upgrade the database version to 5. Only >> > once that succeeds fail req1 by firing an "error" event at it. If req2 >> > failed to upgrade the database (due to a aborted transaction), then >> > fire a "upgradeneeded" transaction on req1. >> > >> > This seems like a really rare edge case and I don't think it matters >> > much what we do. I chose to go with option B since it results in the >> > least amount of errors and it doesn't seem particularly important to >> > optimize for failing open calls quickly in this rare situation. >> > >> > I don't think it matters much what we choose here. I think it's very >> > unlikely to matter in any real-world scenarios. I might even be fine >> > with letting implementations choose to go with either solution here. >> > >> > >> > * What to do if indexedDB.open is called while a VERSION_CHANGE >> > transaction is pending, but the new call is for a higher version. >> > Consider the following scenario: >> > >> > 1. A database with name "mydb" and version 1 is currently open in tab 1. >> > 2. Someone calls indexedDB.open("mydb", 2) in tab 2. >> > 3. The indexedDB implementation fires a "versionchange" event on the >> > open connection in tab 1 and waits for it to close. The newVersion >> > property of the event is set to 2. >> > 4. Someone calls indexedDB.open("mydb", 3) in tab 3. >> > >> > At this point there are at least two options: >> > A) Simply let the call in step 4 wait for the call in step 2 to >> > finish. Only after it has finished will we fire new events to attempt >> > an upgrade to version 3 >> > B) Stall the upgrade two version 2 and instead start attempting an >> > upgrade to version 3. I.e. fire a new "versionchange" event on the >> > open connection in tab 1 (now with newVersion set to 3), and once that >> > connection is closed, fire a "upgradeneeded" event and start a >> VERSION_CHANGE transaction in tab 3. >> > >> > Option A basically makes us behave as if the call in step 4 happened >> > after the VERSION_CHANGE transaction for the call in step 2 had >> > started. Option B almost makes us behave as if the calls in step 2 and >> > step 4 had happened at the same time (with the exception that two >> > "versionchange" events are fired). >> > >> > As with the previous issue I don't think it matters much what we >> > choose here. I think it's very unlikely to matter in any real-world >> > scenarios. I might even be fine with letting implementations choose to >> > go with either solution here. >> > >> > >> > * What to do if db.close() is called during the VERSION_CHANGE >> > transaction Calling db.close() during a VERSION_CHANGE transaction >> > somewhat similar to calling transaction.abort(). At least in the sense >> > that in neither case does it make sense for >> > IDBFactorySync.open/IDBFactory.open to complete successfully. I.e. it >> > would seem strange to let IDBFactorySync.open return a closed >> > database, or to fire a "success" event on the request returned by >> IDBFactory.open and then deliver a closed database. >> > >> > We could make db.close() throw an exception in this case, but that >> > seems like a odd behavior for db.close() compared to how it usually >> > interacts with running transactions (i.e. it usually lets them finish). >> > >> > I'm instead leaning towards letting the VERSION_CHANGE transaction >> > continue running, but make IDBFactorySync.open throw an exception and >> > fire an "error" event on the request returned from IDBFactory.open. >> > >> > In fact, after thinking about this some more I checked in a change to >> > the spec to make it define that behavior. The main problem was that we >> > don't have a really good error for this situation. I decided to return >> > a ABORT_ERR error, but if anyone has other suggestions, or think we >> > should use should use a dedicated error, I'm fine with that too. >> > >> > If people feel that we should use another solution, please do speak >> > up. It's easy to back out my patch :-) >> > >> > / Jonas >> >> Thanks for making these changes to the spec so quickly. Here is some >> feedback: >> >> * In order to support Section 4.1 step #4, it seems we want to follow the >> same advance number logic and not allow any zero or negative numbers to >> be defined by the developer for the version. This will allow this step to >> happen without any issues. Otherwise, we will be creating a default db with >> version "0" and the value would be negative or "0" which would cause step >> #5 to execute. It seems we want to throw an exception with a >> NON_TRANSIENT_ERR if the developer specifies any zero or negative version >> values (similar to advance). >> >> * We also believe that the version number should be optional. We see >> scenarios where the developer would want to use the latest db and not have >> to worry about the version number. If a version number is not specified and >> the db doesn't exists, we will throw a NOT_FOUND_ERR. We only way to >> create a new db when the version is specified. This will prevent the >> onupgradeneeded event handler from being called when there is no version >> specified. >> >> * We don't believe developers shouldn't be allowed to start a new >> transaction from the onabort handler associated with a VERSION_CHANGE >> transaction. The reason is that we don't consider the db to be in a valid >> state >> because the open operation associated with the db handle failed to execute >> properly. >> >> * Similarly, if the VERSION_CHANGE transaction fails to commit (db failure or >> abort method is called) we believe the db version should be set to undefined >> on the onabort handler. We don't see the point of going back to the server >> to get the last committed version number because the intent of the >> developer was to operate on the new schema which failed to commit. It >> seems that if they want to use the latest schema they could open the db >> without specifying a version. >> >> * It seems that if a user aborts the VERSION_CHANGE transaction, we should >> call the onerror handler of the open database method. This will ensure that >> the onsuccess logic that follows a clean transaction commit will not be >> executed, possibly generating additional errors. >> >> Israel >> > > One more thing, in section 4.8, we probably should set the done flag to true > in order to specify that the attributes associated with the request are > accessible. We don't believe this should have any side effects on the > onsuccess or onerror handlers.
Hmm.. I think you're right. That would be an additional sub-step before the current sub-steps in step 9? / Jonas
