Mailspring/internal_packages/sidebar-fullcontact/lib/fullcontact-store.coffee
Ben Gotow a14a5212ac feat(transactions): Explicit (and faster) database transactions
Summary:
Until now, we've been hiding transactions beneath the surface. When you call persistModel, you're implicitly creating a transaction.
You could explicitly create them with `atomically`..., but there were several critical problems that are fixed in this diff:

- Calling persistModel / unpersistModel within a transaction could cause the DatabaseStore to trigger. This could result in other parts of the app making queries /during/
  the transaction, potentially before the COMMIT occurred and saved the changes. The new, explicit inTransaction syntax holds all changes until after COMMIT and then triggers.

- Calling atomically and then calling persistModel inside that resulted in us having to check whether a transaction was present and was gross.

- Many parts of the code ran extensive logic inside a promise chained within `atomically`:

  BAD:

```
  DatabaseStore.atomically =>
   DatabaseStore.persistModel(draft) =>
     GoMakeANetworkRequestThatReturnsAPromise
```

OVERWHELMINGLY BETTER:

```
  DatabaseStore.inTransaction (t) =>
     t.persistModel(draft)
  .then =>
    GoMakeANetworkRequestThatReturnsAPromise
```

Having explicit transactions also puts us on equal footing with Sequelize and other ORMs. Note that you /have/ to call DatabaseStore.inTransaction (t) =>. There is no other way to access the methods that let you alter the database. :-)

Other changes:
- This diff removes Message.labels and the Message-Labels table. We weren't using Message-level labels anywhere, and the table could grow very large.
- This diff changes the page size during initial sync from 250 => 200 in an effort to make transactions a bit faster.

Test Plan: Run tests!

Reviewers: juan, evan

Reviewed By: juan, evan

Differential Revision: https://phab.nylas.com/D2353
2015-12-17 11:46:05 -08:00

42 lines
1.2 KiB
CoffeeScript

_ = require 'underscore'
Reflux = require 'reflux'
request = require 'request'
{Contact,
AccountStore
ContactStore,
DatabaseStore,
FocusedContactsStore} = require 'nylas-exports'
FullContactStore = Reflux.createStore
init: ->
dataForContact: (contact) ->
return {} unless contact
if contact.thirdPartyData["FullContact"]
return contact.thirdPartyData["FullContact"]
else
@_attachFullcontactDataToContact(contact)
return {}
_attachFullcontactDataToContact: (contact) ->
email = contact.email.toLowerCase().trim()
return if email.length is 0
url = "https://api.fullcontact.com/v2/person.json?email=#{email}&apiKey=eadcbaf0286562a"
request url, (err, resp, data) =>
return if err
return if resp.statusCode != 200
try
data = JSON.parse(data)
contact.title = data.organizations?[0]?["title"]
contact.company = data.organizations?[0]?["name"]
contact.thirdPartyData ?= {}
contact.thirdPartyData["FullContact"] = data
DatabaseStore.inTransaction (t) =>
t.persistModel(contact)
.then =>
@trigger()
module.exports = FullContactStore