W3C home > Mailing lists > Public > public-webapps@w3.org > April to June 2010

Re: [IndexedDB] Atomic schema changes

From: Jonas Sicking <jonas@sicking.cc>
Date: Tue, 29 Jun 2010 13:40:12 -0700
Message-ID: <AANLkTinv6Tsurn2k7HYFYI7X-0otoqFzA6p1yWCEmTKs@mail.gmail.com>
To: Jeremy Orlow <jorlow@chromium.org>
Cc: Webapps WG <public-webapps@w3.org>
On Sun, Jun 27, 2010 at 12:27 AM, Jonas Sicking <jonas@sicking.cc> wrote:
>>> >> > But, I feel pretty strongly that a setVersion/schema change
>>> >> > transaction
>>> >> > should not simply kill off anything else currently running.  The
>>> >> > reason
>>> >> > is
>>> >> > that it's not hard for apps to recover from a connection failing, but
>>> >> > it
>>> >> > is
>>> >> > hard to handle a transaction failing in an unpredictable way.
>>> >> >  Especially
>>> >> > static transactions (which should rarely fail committing since
>>> >> > serialization
>>> >> > can be guaranteed before the transaction starts).
>>> >>
>>> >> That might be a good idea for v1. I was planning on doing a separate
>>> >> thread for setVersion, but maybe it's tied enough to the topic of
>>> >> schema changes that it makes sense to bring up here.
>>> >>
>>> >> What I suggest is that when setVersion is called, we fire
>>> >> 'versionchange' event on all other open IDBDatabase objects. This
>>> >> event contains information of what the desired new version number is.
>>> >> If no other IDBDatabase objects are open for the specific database, no
>>> >> 'versionchange' events are fired. This allows pages using the old
>>> >> schema version to automatically save any pending data (for example any
>>> >> draft emails) and display UI to the user suggesting that the tab be
>>> >> closed. If possible without dataloss, the tab could even reload itself
>>> >> to automatically load an updated version of the page which uses the
>>> >> new schema version.
>>> >>
>>> >> The 'versionchange' event would use an interface like
>>> >>
>>> >> interface IDBVersionEvent : IDBEvent {
>>> >>  readonly attribute string version;
>>> >> };
>>> >
>>> > First of all, what I was originally advocating (sorry for not being
>>> > clear)
>>> > is that we should kill the database connection but not until all active
>>> > transactions are complete.  Though we should probably block new
>>> > transactions
>>> > from starting once setVersion is called.
>>> > But I really like your versionchange event idea regardless.  I agree
>>> > that
>>> > letting the app sync any data that might be in memory (for example, a
>>> > draft
>>> > email) is important.  And the idea that the web app could refresh itself
>>> > (or
>>> > download new application code or something) seems pretty cool and
>>> > useful.
>>> >  I'm fine with it firing on all frames except the one that initiated
>>> > (like
>>> > storage events).  If we go with the "kill the connection once all active
>>> > transactions are done and block new ones from starting", we'd want to
>>> > start
>>> > the blocking only after all versionchange events have finished.
>>> > The main reason that I like the idea of not stating the version change
>>> > until
>>> > all active connections have closed is that not all apps will handle
>>> > versionchange.  My original idea was that we should just break such web
>>> > apps
>>> > and let the user refresh, but now that you've pointed out the potential
>>> > for
>>> > data loss I'm not sure that's an option.  Savvy web apps can kill all
>>> > existing database connections when they get the versionchange and thus
>>> > avoid
>>> > stalling things.
>>> >
>>> >> Additionally, if there are open IDBDatabase objects, we fire a
>>> >> 'blocked' event at the IDBRequest object returned from the setVersion
>>> >> call. This allows the page to display UI to the user asking the user
>>> >> to close all other relevant tabs.
>>> >>
>>> >> Once all other IDBDatabase objects are closed, we create a transaction
>>> >> and fire the normal 'success' event.
>>> >>
>>> >> While there are pending version change requests, no success events are
>>> >> fired for calls to IDBFactory.open for the relevant database.
>>> >>
>>> >> We might want to support forcefully killing off open IDBDatabase
>>> >> objects in the future, but I think that can wait until after v1.
>>> >
>>> > Really?  I can't see an app like gmail ever asking users to close tabs.
>>> >  I
>>> > bet they'd sooner run all the application logic in an iframe and
>>> > navigate it
>>> > away when doing a schema change.
>>> > And I don't see many people correctly implementing a blocked event
>>> > handler.
>>> >  If anything, it should be an error code.
>>> > It doesn't seem that hard to have an explicit way to tell the database
>>> > explicitly "OK, I'm done".  Or, at very least, we could make it so that
>>> > when
>>> > there's an existing setVersion happening, all new connection requests
>>> > stall.
>>> >  That way all pages can reload themselves but they won't connect to the
>>> > database until the upgrade is complete.
>>> > But really...all of this is really hacky.  I'm starting to wonder if we
>>> > should just kill the database connections on a setVersion as I
>>> > originally
>>> > tried to suggest.
>>>
>>> I'm pretty concerned though that sites will need to take asynchronous
>>> actions in order to save all required data. While gmail happily
>>> automatically saves every few minutes, and presumably could
>>> immediately do so upon a 'versionchange' event, I don't think all
>>> editors are willing t. For example many editors ask the user if they
>>> want to save the current changes when they are closed, in order to not
>>> overwrite correct data.
>>>
>>> Additionally, there is always the risk that developers will forget to
>>> use a versionchange event handler to protect their data. I think a
>>> good design principal is that if sites do the minimal amount of work,
>>> that should default to safe behavior.
>>>
>>> I do realize that not all applications are willing to do the "please
>>> close all other tabs" UI thing. But for those we would provide enough
>>> tools do something better. If we add a IDBDatabase.close() function
>>> then applications that can easily emulate the "force-close open
>>> connections" using that and the versionchange event. And they could
>>> even use that to implement asynchronous data saving for when that is
>>> required.
>>
>> Yeah.  I think giving developers a .close() (or maybe even a
>> .closeOthers()?) should be enough.  It still feels clunky to me, but I also
>> think it'd be dangerous to over-design this without some feedback from
>> several developers using this in the real world...which won't happen until
>> we ship something (even if its basic).
>
> Ok, I'll file a bug.

Filed http://www.w3.org/Bugs/Public/show_bug.cgi?id=10052

Please check that I documented the right thing. I wasn't sure if we
decided to move createObjectStore/removeObjectStore to a new type of
transaction or not. I kept it on IDBDatabase for now since we can't
move createIndex/removeIndex anyway.

/ Jonas
Received on Tuesday, 29 June 2010 20:41:06 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 18:49:39 GMT