Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple operations per transaction, with Treo sugar #32

Open
glsignal opened this issue Jul 4, 2015 · 5 comments
Open

Support multiple operations per transaction, with Treo sugar #32

glsignal opened this issue Jul 4, 2015 · 5 comments
Labels

Comments

@glsignal
Copy link

glsignal commented Jul 4, 2015

Currently (as I understand it), Treo opens a transaction for each atomic operation—get, put etc.—allowing for the possibility of data changes between read and write:

var facts = db.store('avocadoFacts');

facts.get(12).then( (realAvocadoFact) =>  {
  // If I wanted to update that record here, that happens in a new transaction. It's possible that some change happens to the record in IndexedDB while I'm playing with it in memory.
  realAvocadoFact.body = "sometimes avocados have bad taste";
  facts.put(realAvocadoFact, () => {
    /* My changes are done and persisted */
  });
});

While it's probably not a huge deal for many applications, I'm running into it fairly frequently (my data is not directly generated by a user interface) and so I'm finding myself falling back to IndexedDB's standard API; opening a big transaction to do my work, and hence losing a lot of the Treo sugar.

(I'll note that I'm working in a chrome extension too, so there are multiple JS environments executing at any given time, all with access to the same IndexedDB stores).

db.transaction("readwrite", ["avocadoFacts"], (err, tx) => {
  var facts = tx.objectStore("avocadoFacts");

  facts.get(12).onsuccess = (evt) => {
    var realAvocadoFact = evt.target.result; 
    realAvocadoFact.body = "sometimes avocados have bad taste";
    facts.put(realAvocadoFact);
  };

  tx.oncomplete = () => {
    /* My changes are done and persisted */
  };
});

I was wondering if there were any plans for a feature like chaining reads and writes together in a single transaction (effectively making an update call that's much less verbose than the IndexedDB equivalent), or any thoughts on how difficult it might be to carry over the transaction to arbitrary actions on data.

This is a little hairy and ill-defined, but for instance here's some code I'd like to be able to write:

var facts = db.store('avocadoFacts');

facts.openTransaction()
  .get(12)
  .put( (realAvocadoFact) =>  {
    realAvocadoFact.body = "sometimes avocados have bad taste";
    return realAvocadoFact; // return value is persisted and passed to any chained functions
  })
  .done( (realAvocadoFact) => {
    /* My changes are done and persisted */
  });
});

Terrible API aside (very little thought has gone into it; I just want to open the discussion), is it clear what I'm getting at? The example above (updating a record) might be better as a plugin's job, but I'd be interested to hear your thoughts on making better use of transactions in situations like these, and addressing the root cause. Transactions as a concept are extremely useful, but I feel like they're being under utilised.

@alekseykulikov
Copy link
Contributor

Hi,
In spare time I'm currently working on treo 0.6 #29, which supports transaction reuse. I like your API, but I decided to build it closer to "treo way":

var tr = db.transaction('write', ['avocadoFacts', 'tomatoNotes'])
var facts = tr.store('avocadoFacts')
var notes= tr.store('tomatoNotes')

facts.put(1, { body: 'sometimes avocados have bad taste' })
facts.put(2, { body: 'avocados are expensive in some areas' })
notes.put(1, { body: 'tomato soup is good!' })

tr.then(function() {
  console.log('transaction is complete')
}).catch(function(err) {
  console.error(err)
})

So, for now I just need to finish 0.6 release. Code is mostly done, need to update docs and test in IE :)

Treo opens a transaction for each atomic operation—get, put etc

Yes, the reason treo designed this way, because it makes API easier and allows to avoid cross-browser issues. Safari and IndexedDBShim has bad support of transaction reuse.

@alekseykulikov alekseykulikov mentioned this issue Jul 6, 2015
18 tasks
@glsignal
Copy link
Author

glsignal commented Jul 6, 2015

Ah this is perfect - I hadn't seen the final API for 0.6.

I'd started to write a small plugin which allowed for a lot of the same things that 0.6 does, so I shall grab the release candidate and use that instead.

Thanks :)

@alekseykulikov
Copy link
Contributor

You are welcome.

0.6.0-rc1 is pretty stable, I'm just diving to transaction implementation and test it carefully. A few things to keep in mind:

Let me know, how it works :)

@glsignal
Copy link
Author

glsignal commented Jul 7, 2015

I'm working in a Chrome extension so these shouldn't be issues - I'll let you know how it goes :)

If it interests you, I've been using async functions to de-noise the code in the plugin I mentioned:

screenshot from 2015-07-06 18-09-45
(it's a pointless use-case in this screenshot (because of Treo's get), but other store operations could happen in a similar fashion)

This still seems like it would be compatible with Treo's new API, so I might still work on that plugin as it removes a bit more boilerplate from the transaction usage.

@alekseykulikov
Copy link
Contributor

Nice :)
Yes, treo's migration to promises was guided by ES7 async/await syntax and growing adoptions of ES6 Promises.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants