Re: IndexedDB, what were the issues? How do we stop it from happening again?

On Wed, Mar 6, 2013 at 10:14 AM, Alec Flett <alecflett@chromium.org> wrote:
> My primary takeaway from both working on IDB and working with IDB for some
> demo apps is that IDB has just the right amount of complexity for really
> large, robust database use.. but for a "welcome to noSQL in the browser" it
> is way too complicated.
>
> Specifically:
>
> versioning - The reason this exists in IDB is to guarantee a schema (read: a
> fixed set of objectStores + indexes) for a given set of operations.
> Versioning should be optional. And if versioning is optional, so should
> opening - the only reason you need to "open" a database is so that you have
> a handle to a versioned database. You can almost implement versioning in JS
> if you really care about it...(either keep an explicit key, or auto-detect
> the state of the schema) its one of those cases where 80% of versioning is
> dirt simple  and the complicated stuff is really about maintaining version
> changes across multiply-opened windows. (i.e. one window opens an idb, the
> next window opens it and changes the schema, the first window may need to
> know that and be able to adapt without breaking any in-flight transactions)

Yeah, the versioning is the part of the API that I'm least happy with.

The reason we need it is because we're synchronously exposing the
"schema" of the database. Instead we could have made the set of object
stores and indexes entirely dynamic and created on-demand.

However that would have made it tricky to do schema which has
constraints (like the "unique" index-flag) or that affects how data is
stored (for example the ability to set a collation on an objectStore
or index as has been discussed).

> transactions - Also should be optional. Vital to complex apps, but totally
> not necessary for many.. there should be a default transaction, like
> db.objectStore("foo").get("bar")

I disagree. This would have made it too trivial to create pages that
have race conditions. I.e. people would write code like:

db.objectStore("foo").get("bar").onsuccess = function(e) {
  db.objectStore("foo").set("bar", e.target.result + 1)
}

without realizing that that contains a race condition.

> transaction scoping - even when you do want transactions, the api is just
> too verbose and repetitive for "get one key from one object store" -
> db.transaction("foo").objectStore("foo").get("bar") - there should be
> implicit (lightweight) transactions like db.objectStore("foo").get("bar")

We used to have this exact syntax, but it got everyone confused about
what how the implicit transaction actually worked.

> forced versioning - when versioning is optional, it should be then possible
> to change the schema during a regular transaction. Yes, this is a lot of
> rope but this is actually for much more complex apps, rather than simple
> ones. In particular, it's not uncommon for more complex database systems to
> dynamically create indexes based on observed behavior of the API, or
> observed data (i.e. when data with a particular key becomes prevalent,
> generate an index for it) and then dynamically use them if present. At the
> moment you have to do a manual close/open/version change to dynamically bump
> up the version - effectively rendering fixed-value versions moot (i.e. the
> schema for version 23 in my browser may look totally different than the
> schema for version 23 in your browser) and drastically complicating all your
> code (Because if you try to close/open while transactions are in flight,
> they will be aborted - so you have to temporarily pause all new
> transactions, wait for all in-flight transactions to finish, do a
> close/open, then start running all pending/paused transactions.) This last
> case MIGHT be as simple as adding db.reopen(newVersion) to the existing
> spec.

Yeah, this is something that I've run into as well. It's tricky to
solve this without removing the ability to synchronously access the
list of objectStores and indexes, or without introducing race
conditions if a page is open in multiple tabs.

> named object stores - frankly, for many use cases, a single objectStore is
> all you need. a simple db.get("foo") would be sufficient. Simply naming a
> "default" isn't bad - whats bad is all the onupgradeneeded scaffolding
> required to create the objectstore in the first place.

I think we should do this as part of a simple API. Similar to something like

https://github.com/slightlyoff/async-local-storage

> I do think that the IDBRequest model needs tweaking, and Futures seem like
> the obvious direction to head in.

Yup. Though see the list of constraints in my previous email in this thread.

> FWIW, the "sync" version of the API is more or less dead - nobody has
> actually implemented it.

We're actually working on an implementation and hope to have it ready mid year.

/ Jonas

Received on Saturday, 16 March 2013 11:21:49 UTC