[whatwg] RFC: Alternatives to storage mutex for cookies and localStorage

Benjamin Smedberg wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> On 9/8/09 3:00 AM, Aaron Boodman wrote:
>> On Fri, Sep 4, 2009 at 12:02 AM, Chris Jones<cjones at mozilla.com> wrote:
>>> I propose adding the functions
>>>
>>>  window.localStorage.beginTransaction()
>>>  window.localStorage.commitTransaction()
>>> or
>>>  window.beginTransaction()
>>>  window.commitTransaction()
>> I think this is a good idea! I would modify it to follow the pattern
>> set by the current SQLDatabase proposal, to have a callback, like
>> this:
>>
>> window.localStorage.transaction(function() {
>>   // use local storage here
>> });
> 
> To be specific, the .transaction function would enqueue an operation to
> perform at a later time when a mutex was held. The current caller would
> continue to run to completion. There would never be simultaneous
> transactions which could potentially conflict with eachother and require
> merging or rollback.
> 
> It wasn't clear to me when this was proposed that it was asynchronous,
> instead of a blocking call that *immediately* waited for the mutex and
> blocked script execution.
> 

To be clear, that's not what I had in mind at all.  I envisioned a 
synchronous API that speaks in terms of fallible, atomic/consistent 
transactions.  Mutexes are implementation details that the spec would 
not mention.

It's easy to make an async API out of a sync one by using setTimeout(0, 
...).  It's harder to go the other way.

> Would the transaction function be defined so that it never runs immediately
> but is always enqueued? Also, I think the function name should make it
> clearer that it's an asynchronous callback:
> window.localStorage.queueTransaction or somesuch?
> 
>> I'm against having explicit begin/commit methods for the same reason
>> as I am for the SQLDatabase feature:
>>
>> - It is easy to forget to commit
>> - The most likely paths in an application to be wrong are ones that
>> are rarely run
>> - Therefore many applications will contain uncommon paths that end up
>> hung (responsive, but still unable to make forward progress) and with
>> uncommitted data
> 
> I agree that this is true if you never implicitly commit the transaction.
> But if you were to implicitly commit the transaction when a script runs to
> completion, would that negate the most serious of these issues? I'm defining
> "completion" as "all those places where the current spec says the storage
> mutex is unlocked", which seems equivalent to "the places script can block
> on network or UI activity".
> 

It sounds like you're proposing to make the unit of run-to-completion 
implicitly delineate localStorage transactions?  This is fine but it 
complicates the handling of failed transactions, IMHO.

> I suspect that making incompatible changes to the existing storage API is
> going to be a hard sell for some authors: could we continue to support
> completely transaction-free access to storage, in addition to the race-free
> queued version. This would allow authors (JS libraries) to do
> runtime-detection of the form:
> 
> if (window.localStorage.transaction === undefined)
>   window.localStorage.transaction = function(fn) {
>     window.setTimeout(fn, 0);
>   };
> 

No one has responded directly to my original proposal of making 
|window.localStorage === undefined| until |window.transaction| or 
whatever has been accessed.  Unlike your proposal and a similar one from 
Jeremy, mine is a "safe" (non-racy) way for spec-compliant UAs to "bend" 
backwards compatibility without explicitly breaking it.  Web apps slow 
to change should theoretically be prepared for |window.localStorage === 
undefined| anyway, as not all UAs support localStorage.  And if a UA 
doesn't support window.transaction, a web app that cares never needs to 
worry about racy localStorage because in non-compliant UAs, 
|window.transaction === undefined|.

Cheers,
Chris

Received on Tuesday, 8 September 2009 13:38:33 UTC