mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-14 21:57:55 +08:00
1e34a2e33b
Summary: This commit modifies the api of NylasAPIRequest to /not/ take `success` or `error` callback options at all, and only returns a Promise which you can `then` and `catch` to handle the api response. The fact that it returned a promise, and /also/ took `success` and `error` callback options made it really confusing to use. Additionaly, when using the callbacks intead of a promise, any errors would be unhandled and reported to Sentry because even though the `error` callback was being passed, the promise returned by `run()` still rejected and no one was handling that reject, so it reached the `unhandledRejection` event listener. This is undesirable because if you passed an `error` callback, it means that you intended to handle it. An example of this is calling the clearbit API, which will more often than not return a 404, and even though we had an error handler which ignored the 404, it still unecessarilly reported to Sentry, flooding it with events Test Plan: manually check all updated codepaths still work Reviewers: halla, spang, evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D3869
88 lines
2.1 KiB
JavaScript
88 lines
2.1 KiB
JavaScript
import {DatabaseStore, Utils} from 'nylas-exports'
|
|
import NylasStore from 'nylas-store'
|
|
import ClearbitDataSource from './clearbit-data-source'
|
|
|
|
// TODO: Back with Metadata
|
|
const contactCache = {}
|
|
const CACHE_SIZE = 100
|
|
const contactCacheKeyIndex = []
|
|
|
|
class ParticipantProfileStore extends NylasStore {
|
|
activate() {
|
|
this.cacheExpiry = 1000 * 60 * 60 * 24 // 1 day
|
|
this.dataSource = new ClearbitDataSource()
|
|
}
|
|
|
|
dataForContact(contact) {
|
|
if (!contact) {
|
|
return {}
|
|
}
|
|
|
|
if (Utils.likelyNonHumanEmail(contact.email)) {
|
|
return {}
|
|
}
|
|
|
|
if (this.inCache(contact)) {
|
|
const data = this.getCache(contact);
|
|
if (data.cacheDate) {
|
|
return data
|
|
}
|
|
return {}
|
|
}
|
|
|
|
this.dataSource.find({email: contact.email}).then((data) => {
|
|
if (data && data.email === contact.email) {
|
|
this.saveDataToContact(contact, data)
|
|
this.setCache(contact, data);
|
|
this.trigger()
|
|
}
|
|
}).catch((err = {}) => {
|
|
if (err.statusCode !== 404) {
|
|
throw err
|
|
}
|
|
})
|
|
return {}
|
|
}
|
|
|
|
// TODO: Back by metadata.
|
|
getCache(contact) {
|
|
return contactCache[contact.email]
|
|
}
|
|
|
|
inCache(contact) {
|
|
const cache = contactCache[contact.email]
|
|
if (!cache) { return false }
|
|
if (!cache.cacheDate || Date.now() - cache.cacheDate > this.cacheExpiry) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
setCache(contact, value) {
|
|
contactCache[contact.email] = value
|
|
contactCacheKeyIndex.push(contact.email)
|
|
if (contactCacheKeyIndex.length > CACHE_SIZE) {
|
|
delete contactCache[contactCacheKeyIndex.shift()]
|
|
}
|
|
return value
|
|
}
|
|
|
|
/**
|
|
* We save the clearbit data to the contat object in the database.
|
|
* This lets us load extra Clearbit data from other windows without
|
|
* needing to call a very expensive API again.
|
|
*/
|
|
saveDataToContact(contact, data) {
|
|
return DatabaseStore.inTransaction((t) => {
|
|
if (!contact.thirdPartyData) contact.thirdPartyData = {};
|
|
contact.thirdPartyData.clearbit = data
|
|
return t.persistModel(contact)
|
|
})
|
|
}
|
|
|
|
deactivate() {
|
|
// no op
|
|
}
|
|
}
|
|
const store = new ParticipantProfileStore()
|
|
export default store
|