On Fri, Jul 22, 2011 at 9:51 AM, Israel Hilerio <[email protected]> wrote:
> On Thursday, July 14, 2011 5:27 PM, Israel Hilerio wrote:
>> On Thursday, July 14, 2011 1:57 PM, Jonas Sicking wrote:
>> > On Thu, Jul 14, 2011 at 1:20 PM, Israel Hilerio <[email protected]>
>> wrote:
>> > > On Wednesday, July 13, 2011 2:02 PM, Jonas Sicking wrote:
>> > >> On Wed, Jul 13, 2011 at 11:39 AM, Israel Hilerio
>> > >> <[email protected]>
>> > >> wrote:
>> > >> > What should be the client state after a deleteIndex is called?
>> > >> > For example looking at the code below:
>> > >> >
>> > >> > 1. var index = objStore.index(indexName); 2.
>> > >> > objStore.deleteIndex(indexName); 3. try { 4.
>> > >> > index.openCursor().onerror = function (e) { log("failed to open
>> > >> > cursor"); } 5. } catch (ex) { 6.      log ("failed to call
>> > >> > openCursor"); 7. }
>> > >> >
>> > >> > Similar to our previous conversation around transaction.abort, it
>> > >> > seems that
>> > >> we would want to keep some knowledge on the client that the index
>> > >> was deleted at line #2 and therefore, line #4 will throw an
>> > >> exception that will be handled by line #6.  In this case, the
>> > >> onerror handler at line #4 will never be executed.
>> > >> >
>> > >> > Do you agree?
>> > >>
>> > >> Yes! I do think we need to modify the spec to specify this.
>> > >>
>> > >> > Would it be good enough to just throw an UNKNOWN_ERR or we could
>> > >> create a new error code for this (e.g. CALLER_ERR or OBJECT_ERR).
>> > >>
>> > >> I would say NOT_ALLOWED_ERR or NOT_FOUND_ERR would be ok for
>> this
>> > >> case.
>> > >>
>> > >> > Also, what should happen to deleteObjectStore when it is called
>> > >> > in a similar
>> > >> situation:
>> > >> >
>> > >> > 1. var objStore = db.createObjectStore(osName, {keyPath: "name"}); 2.
>> > >> > db.deleteObjectStore(osName); 3. try { 4.
>> > >> > objStore.index(indexName); 5. } catch (ex) { 6.     Log ("failed
>> > >> > to call index"); 7. }
>> > >> >
>> > >> > I would also expect us to keep knowledge on the client that the
>> > >> > objStore
>> > >> was deleted at line #2 and therefore not allow line #4 from queuing
>> > >> up a request but fail fast with an exception.  We could throw the
>> > >> same exception as the example above.
>> > >> >
>> > >> > Do you agree?
>> > >>
>> > >> Yup. Seems identical to the situation you described above.
>> > >>
>> > >> By the way, I assume this is only relevant during VERSION_CHANGE
>> > >> transactions, right?
>> > >>
>> > >> Another tricky situation is what to do with code like
>> > >>
>> > >> 1. var index = objStore.index(indexName); 2. req = index.get(2); 3.
>> > >> req.onsuccess = function() { log("didn't fail, value is" + req.result) 
>> > >> }; 4.
>> > >> req.onerror = function() { log("error was fired") }; 5.
>> > >> objStore.deleteIndex(indexName);
>> > >>
>> > >> I don't feel strongly what should happen. From an implementation
>> > >> point of view it might be easy either way. In fact I think in the
>> > >> Gecko implementation it might be easier to the request succeed and
>> > >> deliver the same data as if the index hadn't been deleted, than to
>> > >> let it fail. This is because all requests run on the same database
>> > >> thread (in order to ensure that they run in the proper order), and
>> > >> so by the time the index is deleted, we have already read data out from
>> it.
>> > >>
>> > >> From a user point of view it might be slightly more useful if the
>> > >> request succeeds, but it also seems quite ok to require that people
>> > >> don't delete an index or objectStore unless they don't expect to
>> > >> get more
>> > data from it.
>> > >>
>> > >> / Jonas
>> > >
>> > > We agree with you that we should let the previously queued up
>> > > operations
>> > finish before the deleteIndex or deleteObjectStore impacts them.
>> > However, after the deleteIndex or deleteObjectStore are executed in
>> > the client, we don't want to allow further calls to be invoked on
>> > these objects.  We want to immediately throw an exception
>> > (NOT_ALLOWED_ERR).  This implies that the client APIs don't have to
>> > wait for the deleteIndex and deleteObjecStore to be processed by the
>> > server and that the source objects will keep some type of information
>> > about their deleted state.  It seems a waist of cycles, to allow these
>> > operations to be queued on the server to find out that the source objects
>> don't exists any more.
>> > >
>> > > We believe this simplifies the programming model and makes it more
>> > deterministic.
>> > >
>> > > What do you think?
>> >
>> > It sounds like we agree!
>> >
>> > To make sure we're on the same page, here's pulling all the examples
>> > together.
>> >
>> >
>> > 1. var index = objStore.index(indexName); 2.
>> > objStore.deleteIndex(indexName); 3. try {
>> > 4.       index.openCursor().onerror = function (e) { log("failed to
>> > open cursor"); }
>> > 5. } catch (ex) {
>> > 6.      log ("failed to call openCursor");
>> > 7. }
>> >
>> > Here the openCursor call on line 4 should throw, causing the call on
>> > line 6 to execute next. The onerror assignment never happens as the
>> > exception is thrown before that, and thus the log call on line 4 is never
>> called.
>> >
>> >
>> > 1. var objStore = db.createObjectStore(osName, {keyPath: "name"}); 2.
>> > db.deleteObjectStore(osName); 3. try {
>> > 4.     objStore.index(indexName);
>> > 5. } catch (ex) {
>> > 6.     log("failed to call index");
>> > 7. }
>> >
>> > Here the index call on line 4 should throw, causing the call on line 6
>> > to execute next.
>> >
>> >
>> > 1. var index = objStore.index(indexName); 2. req = index.get(2); 3.
>> > req.onsuccess = function() { log("didn't fail, value is" + req.result) }; 
>> > 4.
>> > req.onerror = function() { log("error was fired") }; 5.
>> > objStore.deleteIndex(indexName); 6.
>> > db.deleteObjectStore(objStore.name);
>> >
>> > Here the function assigned to the onsuccess property on line 3 will
>> > eventually be called and will log whatever value is stored for in the
>> > index at key 2 (or if no such value was stored, it'll log
>> > <undefiend>). The function assigned to the onerror handler on line 4 is
>> never called.
>> >
>> > The same thing would happen if line 5 was removed as removing an
>> > objectStore also removes all its indexes.
>> >
>> >
>> > Another even more complex scenario not brought up yet:
>> >
>> > 1. var index = objStore.index(indexName); 2. req = index.openCursor(); 3.
>> > req.onsuccess = function() { var curs = res.result; if (curs) {
>> > log("found value " + curs.value); curs.continue(); } }; 4. req.onerror
>> > = function() { log("error was
>> > fired") }; 5. objStore.deleteIndex(indexName);
>> >
>> > In this scenario the function assigned to the onsuccess property on
>> > line 3 is called once and will log the first value in the index.
>> > However when that function calls curs.continue, the call to continue
>> > will throw an exception as the index has been deleted.
>> >
>> > Hence the onsuccess function will only be called once, and the onerror
>> > function won't be called at all.
>> >
>> >
>> > Does this match your understanding?
>> >
>> > / Jonas
>>
>> Thanks for putting the last example together.
>> Yes, this matches our understanding.
>>
>> Israel
>>
>
> Jonas,
>
> Would it be good enough to document the above examples under the deleteIndex 
> and deleteObjectStore APIs, respectively? Or do you believe we should add 
> some text to the API descriptions to make this more clear?  In addition, I 
> believe we should expand the explanation for when NOT_ALLOWED_ERR can be 
> thrown to accommodate this case.
>
> Let me know what you prefer?

It would probably also be the most consistent to ensure that all
functions that create requests explicitly mention that a
NOT_ALLOWED_ERR is thrown if the source has been removed. So in the
cases where these functions already throw NOT_ALLOWED_ERR, adding this
additional condition to that description would be a good idea.

Does that answer the question?

Oh, and yes, expanding the explanation for NOT_ALLOWED_ERR seems like
a good idea.

/ Jonas

Reply via email to