Re: IndexedDB: IDBOpenDBRequest sequencing

On Feb 26, 2013 5:19 PM, "Joshua Bell" <jsbell@chromium.org> wrote:
>
> On Tue, Feb 26, 2013 at 5:02 PM, Jonas Sicking <jonas@sicking.cc> wrote:
>>
>> On Fri, Dec 21, 2012 at 11:26 AM, Joshua Bell <jsbell@chromium.org>
wrote:
>> > I was playing around with the following sample:
>> >
>> > <!DOCTYPE html>
>> > <script>
>> >   var dbname = 'db' + Date.now();
>> >   function show(m) { return function() { console.log(m); }; }
>> >   openRequest1 = indexedDB.open(dbname, 1);
>> >     openRequest1.onblocked = show("openRequest1 - blocked");
>> >     openRequest1.onsuccess = function() {
>> >       console.log("openRequest1 - success");
>> >
>> >       openRequest2 = indexedDB.open(dbname, 2);
>> >       openRequest2.onblocked = show("openRequest2 - blocked");
>> >       openRequest2.onsuccess = show("openRequest2 - success");
>> >
>> >       deleteRequest = indexedDB.deleteDatabase(dbname);
>> >       deleteRequest.onblocked = show("deleteRequest - blocked");
>> >       deleteRequest.onsuccess = show("deleteRequest - success");
>> >
>> >       openRequest3 = indexedDB.open(dbname);
>> >       openRequest3.onblocked = show("openRequest3 - blocked");
>> >       openRequest3.onsuccess = show("openRequest3 - success");
>> > };
>> > </script>
>> >
>> > In both FF17 and IE10 the output is:
>> >
>> > openRequest1 - success
>> > openRequest2 - blocked
>> >
>> > If you manually execute openRequest1.result.close() the output
continues:
>> >
>> > openRequest2 - success
>> > deleteRequest - blocked
>> >
>> > Finally, if you manually execute openRequest2.result.close() the output
>> > concludes:
>> >
>> > deleteRequest - success
>> > openRequest3 - success
>> >
>> > Given the spec, I would have expected that deleteRequest's blocked
event
>> > would be fired immediately when the script was executed rather than
waiting
>> > until the first connection was closed. The second open() call should
follow
>> > the steps in 4.1 "Opening a database" through 6 ("Create a new
connection to
>> > db..."), then in step 7 jump to 4.8 "steps for running a versionchange
>> > transaction", resulting in a blocked event at step 3, and in step 4
waiting
>> > until the first connection closes. So far so good. But in 4.11
"Database
>> > deletion steps" I don't see anything preventing the steps from
starting or
>> > proceeding through step 6, resulting in a blocked event.
>> >
>> > As written, I would expect this behavior:
>> >
>> > openRequest1 - success
>> > openRequest2 - blocked
>> > deleteRequest - blocked
>> >
>> > i.e. the second open creates a connection but the versionchange must
wait so
>> > "blocked" is fired;
>>
>> Agreed so far.
>>
>> > the delete call sets the delete pending flag, but must
>> > also wait so "blocked" is fired. The third connection must wait since
the
>> > delete pending flag is set, so it waits (silently) at 4.1 step 3.
>>
>> I agree that this is what the spec says, but this seems like a spec
>> bug to me. I'd prefer is the "blocked" event was always fired if the
>> "success" event is hindered due to someone keeping the database open.
>> I.e. we should only wait silently there if all open connections to the
>> database (if any) have the closePending flag set.
>>
>
> Agreed in principal - waiting silently doesn't seem helpful. Will need to
ponder how to reflect this in the spec, though.
>
>>
>> > If you manually execute openRequest1.result.close() the second
connection's
>> > versionchange can proceed, leading to:
>> >
>> > openRequest2 - success
>> >
>> > Finally, if you manually execute openRequest2.result.close() there are
no
>> > more connections so the delete can proceed. Once the delete has
completed
>> > the third open can proceed, leading to:
>> >
>> > deleteRequest - success
>> > openRequest3 - success
>> >
>> > I'd chalk this up to browser bugs, but the identical behavior in FF17
and
>> > IE10 gives me pause. One way to model this behavior would be to imply
that
>> > only one IDBOpenDBRequest (either an open or a delete) can be running
>> > against a database at a time. I don't see this stated in the spec, but
it's
>> > a reasonable model.
>> >
>> > Can implementers speak up on their interpretations of the spec? Do we
need
>> > to clarify the spec here one way or another?
>>
>> The current Firefox behavior definitely seems like a bug to me.
>>
>> I think that the proper set of events is either
>>
>> openRequest1 - success
>> openRequest2 - blocked
>> deleteRequest - blocked
>> openRequest3 - blocked
>>
>> or
>>
>> openRequest2 - success
>> deleteRequest - blocked
>> openRequest3 - blocked
>> openRequest1 - error
>>
>> Note that the spec already says that if two requests to open the same
>> database, but with different versions, happens "at the same time" then
>> the one with the higher version number is attempted to be opened first
>> and if that's successful the one with the lower numbers receives an
>> error.
>>
>> See the Notes in 4.1 step 3.
>>
>> "at the same time" is of course hard to define.
>
>
> In my sample, openRequest2/deleteRequest/openRequest3 are made in the
"success" handler of openRequest1, so I'm not sure how the openRequest1
could fail.

Ah, I had missed that.

Then I think the only sensible behavior is that openRequest1 receives
"success" and the others "blocked".

> Agreed that "at the same time" leaves wiggle room for 2 vs. 3, though. 3
also opens with the "current version" which require definition when other
requests are in the process of upgrading the database. I think I suggested
text for that in one of the open bugs.

You mean once openReques1.result.close() is called? If so I agree.

/ Jonas

Received on Friday, 8 March 2013 18:25:06 UTC