inexorabletash / indexeddb-promises

Proposal for incremental support for Promises in the Indexed DB API
48 stars 2 forks source link

Waiting transaction w/ additional requests? #9

Open inexorabletash opened 8 years ago

inexorabletash commented 8 years ago

Need to specify the behavior for:

And also:

The plausible behaviors I can think of are:

  1. Once all of the promises in the transaction's extend lifetime promises fulfill, the state transitions back to "inactive" (or "active" if we happen to be in an IDB event dispatch!), and the previous lifetime rules resume. It can be kicked back to "waiting" by further waitUntil() calls.
  2. We do transition to "committing"; any responses that come back after this point fire the usual events/resolutions, but new requests throw "InvalidStateError".

The former feels more natural to me, but the second makes sense if you consider using waitUntil() to build explicitly committing transactions:

IDBTransaction.prototype.becomeExplicit = function() {
  this.waitUntil(new Promise(resolve => { this._waiting = resolve; }));
};
IDBTransaction.prototype.commitNow = function() { this._waiting(); };

(But I still lean towards the former)

inexorabletash commented 8 years ago

Another data point in favor of behavior 1:

async function doStuff(db, url) {
  const tx = db.transaction('store', 'readwrite');
  const store = tx.objectStore('store');

  let record = await store.get(url);
  if (!record) {
    const p = fetch(url); // Pretend this yields a cloneable thing
    tx.waitUntil(p);
    const r = await p;

    // NOTE: if waitUntil(x) returns x, then above can be just:
    // const r = await tx.waitUntil(fetch(url));

    // NOTE: extend lifetime promises have fulfilled, but don't want to commit yet!
    store.put(r, url);
  }
  return record;
}

If you don't transition back to "active" then you must write the waitUntil() so that it encompasses the entire promise chain. If you do transition back to "active" then it is possible to just waitUntil() a non-IDB operation to "bring it into the fold".

inexorabletash commented 8 years ago

Note that the or "active" if we happen to be in an IDB event dispatch clause needs handling even in the case where there are no more outstanding requests. An important case to get right: the transaction is waiting on one of its own requests. The timing of the dispatch vs. resolution is also critical there - don't want to try and commit too early, nor forget to commit.