Re: [IndexedDB] Atomic schema changes

2010-06-27 Thread Jonas Sicking
On Sat, Jun 26, 2010 at 11:44 AM, Jeremy Orlow jor...@chromium.org wrote:
 On Sat, Jun 26, 2010 at 10:09 AM, Jonas Sicking jo...@sicking.cc wrote:

 On Fri, Jun 25, 2010 at 2:43 AM, Jeremy Orlow jor...@chromium.org wrote:
   I'm OK with making createObjectStore/createIndex synchronous.  It
   would
   definitely make such code cleaner and I don't see a major downside,
   but
   at
   the same time I feel like this API is starting to get kind of ad-hoc
   and
   unintuitive to a new user.  Having the create and the remove
   functions
   completely different and in different places seems weird.
   So I agree with either A or leaving things as originally proposed by
   Jonas
   in [IndexDB] Proposal for async API changes.
 
  Well, there's no reason not to make the same changes to
  removeObjectStore/removeIndex. Though the more I think with this
  design createObjectStore and removeObjectStore can stay on IDBDatabase
  and simply throw if called outside the appropriate transaction
  callback.
 
  Here is the revised proposal:
 
  interface IDBDatabase {
     ...
     IDBObjectStore createObjectStore (in DOMString name, in optional
  DOMString keyPath, in optional boolean autoIncrement);
     void removeObjectStore (in DOMString storeName);
     ...
  };
 
  interface IDBObjectStore {
     ...
     IDBIndex createIndex (in DOMString name, in DOMString keyPath, in
  optional boolean unique);
     IDBRequest removeIndex (in DOMString indexName);
     ...
  };
 
  Where createObjecStore/createIndex throws if a objectStore or index of
  the given name already exists, if the keyPath has an invalid syntax,
  or if the function is called when not inside a version-change
  transaction callback. And removeObjectStore/removeIndex throws if the
  objectStore or index doesn't exist or if the function is called when
  not inside a version-change transaction callback.
 
  Throwing if not inside the right type of callback isn't a super clean
  solution, but is really not that different from how add/put throws if
  called when not inside a READ_WRITE transaction.
 
  Just to be clear, no async function (one that returns an IDBRequest)
  should
  _ever_ throw.  (They should only call onerror.)  I assume you didn't
  mean
  add/put throws literally?

 Well, there's no reason we couldn't make add/put throw if called from
 inside the wrong type of transaction. I guess I don't feel strongly
 about it, but it seems to me that calling put from inside a READ_ONLY
 transaction is a much bigger mistake than writing a duplicate key or
 running out of disc space. Additionally it's a situation where we
 synchronously know that there is a bug in the program.

 When this came up before, the thought was that it'd be confusing to web
 developers which errors would raise immediately and which would call the
 error callback.  My feeling is that consistency is more useful than raising
 right away for errors like this.  (Plus, if we find it hard to get web
 developers to do any error checking, it seems even harder to get them to do
 it in 2 ways.  :-)

Well, I wouldn't expect them to check for put-in-wrong transaction,
and thus have that error bubble up and become a top level error, which
is handled through the usual error reporting mechanisms which should
alert the developer of a bug in their code. So it's actually
intentional that this error is handled different from other errors.

But if everyone else feels otherwise I'll shut up and accept that strategy.

   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 

Re: [IndexedDB] Atomic schema changes

2010-06-27 Thread Jeremy Orlow
On Sun, Jun 27, 2010 at 8:27 AM, Jonas Sicking jo...@sicking.cc wrote:

 On Sat, Jun 26, 2010 at 11:44 AM, Jeremy Orlow jor...@chromium.org
 wrote:
  On Sat, Jun 26, 2010 at 10:09 AM, Jonas Sicking jo...@sicking.cc
 wrote:
 
  On Fri, Jun 25, 2010 at 2:43 AM, Jeremy Orlow jor...@chromium.org
 wrote:
I'm OK with making createObjectStore/createIndex synchronous.  It
would
definitely make such code cleaner and I don't see a major downside,
but
at
the same time I feel like this API is starting to get kind of
 ad-hoc
and
unintuitive to a new user.  Having the create and the remove
functions
completely different and in different places seems weird.
So I agree with either A or leaving things as originally proposed
 by
Jonas
in [IndexDB] Proposal for async API changes.
  
   Well, there's no reason not to make the same changes to
   removeObjectStore/removeIndex. Though the more I think with this
   design createObjectStore and removeObjectStore can stay on
 IDBDatabase
   and simply throw if called outside the appropriate transaction
   callback.
  
   Here is the revised proposal:
  
   interface IDBDatabase {
  ...
  IDBObjectStore createObjectStore (in DOMString name, in optional
   DOMString keyPath, in optional boolean autoIncrement);
  void removeObjectStore (in DOMString storeName);
  ...
   };
  
   interface IDBObjectStore {
  ...
  IDBIndex createIndex (in DOMString name, in DOMString keyPath, in
   optional boolean unique);
  IDBRequest removeIndex (in DOMString indexName);
  ...
   };
  
   Where createObjecStore/createIndex throws if a objectStore or index
 of
   the given name already exists, if the keyPath has an invalid syntax,
   or if the function is called when not inside a version-change
   transaction callback. And removeObjectStore/removeIndex throws if the
   objectStore or index doesn't exist or if the function is called when
   not inside a version-change transaction callback.
  
   Throwing if not inside the right type of callback isn't a super clean
   solution, but is really not that different from how add/put throws if
   called when not inside a READ_WRITE transaction.
  
   Just to be clear, no async function (one that returns an IDBRequest)
   should
   _ever_ throw.  (They should only call onerror.)  I assume you didn't
   mean
   add/put throws literally?
 
  Well, there's no reason we couldn't make add/put throw if called from
  inside the wrong type of transaction. I guess I don't feel strongly
  about it, but it seems to me that calling put from inside a READ_ONLY
  transaction is a much bigger mistake than writing a duplicate key or
  running out of disc space. Additionally it's a situation where we
  synchronously know that there is a bug in the program.
 
  When this came up before, the thought was that it'd be confusing to web
  developers which errors would raise immediately and which would call the
  error callback.  My feeling is that consistency is more useful than
 raising
  right away for errors like this.  (Plus, if we find it hard to get web
  developers to do any error checking, it seems even harder to get them to
 do
  it in 2 ways.  :-)

 Well, I wouldn't expect them to check for put-in-wrong transaction,
 and thus have that error bubble up and become a top level error, which
 is handled through the usual error reporting mechanisms which should
 alert the developer of a bug in their code. So it's actually
 intentional that this error is handled different from other errors.

 But if everyone else feels otherwise I'll shut up and accept that strategy.


Lets start another thread and examine this.  If all the errors can pretty
clearly/intuitively be broken into two groups, then maybe this does make
sense.  (I'll try to do it later today unless you beat me to it.)


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