[whatwg] RFC: Alternatives to storage mutex for cookies and localStorage
Chris Jones
cjones at mozilla.com
Wed Sep 9 09:59:23 PDT 2009
Jeremy Orlow wrote:
> Those who want a queue. I.e. those who want an asynchronous
> callback based interface and the UA will only call one callback
> at a time. Perhaps on a per-origin basis. Note that this can
> never "fail", need to be rolled back, etc.
>
>
> This sounds to me like { traditional transactions, async,
> unobservable transaction failures } which is the same as your first
> camp above except async only. Or are you proposing that the unit of
> atomicity/consistency is not all operations performed in the
> callback; i.e., that modifications done in the callback can be
> partially applied?
>
>
> It's just an implementational difference. A queue means that the event
> loop can continue processing stuff while waiting for the 'lock' (which
> maybe is better described as an 'update token' or something). If you
> implement it as a lock (which you would for a synchronous interface)
> then the event loop is blocked.
>
OK, agreed. What we describe reduce to the same thing --- the "trylock"
implementation Rob O'Callahan and I discussed would also never block the
event loop. But I better understand now what you have in mind. (I'm
not sure which is better, but that's what implementation details are all
about!)
>
> I believe Aaron is in the queue camp with me. I'm becoming more
> and more convinced that Chromium should/will not implement the
> storage mutex at all (even for LocalStorage) unless we can come
> up with a way for event loops to not be blocked. And, as far as
> I can tell, Async interfaces are the only way to accomplish this.
>
>
> In general, agreed. I still believe that a sync API
>
>
> The problem with a sync interface, especially if it's one that can be
> held after the top level script context, is deadlock issues with
> WebDatabase (and possibly others). What's there now doesn't have this
> issue because you'd never have the lock when calling the database
> transaction callback.
>
I didn't think of Web Database, although I had in mind a nonblocking
implementation of localStorage (i.e., no mutex) that would prevent it
from participating in deadlocks.
But in general, nesting transactions, both { localStorage { Web DataBase
} } and { localStorage { localStorage } }, is something the spec should
explicitly disallow. There's not a clearly best way to resolve the
semantic problems that arise. (Note that preventing nested transactions
also eliminates deadlock concerns for mutex implementations.)
>
> with exposed transaction failures
>
>
> You'll only have transaction failures in an optimistic transaction
> model, right? So is that what you're suggesting?
>
>
> (as I proposed in the OP) and the right implementation could do
> quite well. But I now think that an async version of that same API
> could perform even better. In addition, that API is most flexible
> in terms of possible UA implementations.
>
>
> IOW, I think that { traditional transactions, async, observable
> failures } subsumes both { traditional transactions, sync,
> observable failures } (OP's proposal) *and* { traditional
> transactions, async, unobservable failures } (your and Aaron's
> proposal).
>
>
> IMHO there are two remaining questions: first, whether the "ideal"
> localStorage transactional API should allow observable transaction
> failures. I believe that it should, as this allows for the widest
> variety of efficient implementations without changing ACID (best
> effort) guarantees given to authors or significantly complicating
> the localStorage API.
>
>
> What failures could there be in a pesimistic/queue model?
>
I'm trying to think of a "universal failure," something that could arise
in any implementation of any proposal. I think that universal failure
is "exceeded localStorage space quota". (I believe there are others,
but one is enough for this discussion.)
So there are really two questions: first, what happens if you detect
"quota exceeded" in the middle of a localStorage.transaction() callback?
Are the modifications made *up to* the quota exceeded error applied to
backing store? Or are they rolled back? This is the
atomicity/consistency design decision I described: what is the unit of
atomic modification (all applied or none applied).
And second, can scripts be notified that the transaction failed (or was
only partially applied) because of quota exceeded?
AFAICT this is irrespective of sync/async/optimistic/pessimistic/queue.
Any implementation has to deal with this error somehow.
In the current localStorage spec, if a setItem() fails because space is
exhausted, it raises QUOTA_EXCEEDED_ERR and does *not* apply any part of
the change in setItem(). That is, setItem() is atomic --- it either
applies or not (not partially applied). But modifications to
localStorage *before* that failing setItem(), within the same storage
mutex acquire/release set, *are* applied to backing store.
In the Web Database spec, if executing a SQL statement in a Transaction
would cause space quota to be exceeded, then *none* of the statements in
the transaction are executed (i.e. none committed to backing store), and
the Transaction fails with QUOTA_ERR. The unit of atomicity for Web
Database is that Transaction object --- either all statements in
Transaction successfully execute or none do.
I'm not sure whether you're proposing that modifications within a
localStorage.transaction() callback are atomic (all applied or none
applied) in the face of quota exceeded. (I'm proposing that they
*should* be atomic.)
It sounds like you're proposing that scripts *cannot* be notified of
quota exceeded. If this is true, then there are some semantic issues
I'd like to discuss. But I want to make sure we're on the same page
first :). (I'm proposing that scripts *should* be able to be notified
of this.)
> Second, what is the best way to go forward with transactional
> localStorage while remaining backwards-compatible with current
> implementations. One option would be to deprecate localStorage in
> favor of a future, transactional window.domainStorage or somesuch.
>
>
> If we do this, we might as well just adopt something like the
> WebSimpleDatabase proposal (which I still haven't gotten around to
> reading yet) which seems much more powerful in many other ways.
>
Certainly a matter of taste, but I like localStorage's API, I'd like to
see it succeed.
> In addition, for cases like "clear private data", UAs would be
> allowed to silently break storage-mutex isolation for apps using the
> non-transactional API.
>
>
> I think it'd be better if they waited for the lock to be freed.
Should be clear that this is for users of the deprecated,
non-transactional API only. Isolation wouldn't be broken for
transactional users.
By the storage mutex spec, without the caveat that isolation may be
sometimes broken, even non-malicious pages that don't exceed the slow
script timeout might be able to (unknowingly) cooperate to indefinitely
prevent a MELUA from clearing private data (assuming clear private data
isn't a blocking operation in the MELUA). The UA might be able to
prevent that with some fancy footwork, but I don't see the point in
doing that for a deprecated API.
Cheers,
Chris
More information about the whatwg
mailing list