mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-23 08:46:07 +08:00
d1b81b6afe
Summary: Sometimes, when logging out of your NylasID and restarting the app, we would continue making some requests from the worker window that required a NylasID. This would make the app enter a restart loop and become completely unresponsive because when we made a request without a NylasID, we would force the user to log out and restart the app, and then we would again make the requests without the id, ad infinitum. To fix this, we make sure we have a NylasID before making any requests that require it Test Plan: manual Reviewers: halla, evan Reviewed By: halla, evan Differential Revision: https://phab.nylas.com/D4344
115 lines
3.6 KiB
JavaScript
115 lines
3.6 KiB
JavaScript
import {ipcRenderer} from 'electron'
|
|
import {IdentityStore, AccountStore, Actions, NylasAPI, NylasAPIRequest} from 'nylas-exports'
|
|
|
|
const CHECK_HEALTH_INTERVAL = 5 * 60 * 1000;
|
|
|
|
class SyncHealthChecker {
|
|
constructor() {
|
|
this._lastSyncActivity = null
|
|
this._interval = null
|
|
}
|
|
|
|
start() {
|
|
if (this._interval) {
|
|
console.warn('SyncHealthChecker has already been started')
|
|
} else {
|
|
this._interval = setInterval(this._checkSyncHealth, CHECK_HEALTH_INTERVAL)
|
|
}
|
|
}
|
|
|
|
stop() {
|
|
clearInterval(this._interval)
|
|
this._interval = null
|
|
}
|
|
|
|
// This is a separate function so the request can be manipulated in the specs
|
|
_buildRequest = () => {
|
|
return new NylasAPIRequest({
|
|
api: NylasAPI,
|
|
options: {
|
|
accountId: AccountStore.accounts()[0].id,
|
|
path: `/health`,
|
|
},
|
|
});
|
|
}
|
|
|
|
_checkSyncHealth = async () => {
|
|
try {
|
|
if (!IdentityStore.identity()) {
|
|
return
|
|
}
|
|
const request = this._buildRequest()
|
|
const response = await request.run()
|
|
this._lastSyncActivity = response
|
|
} catch (err) {
|
|
if (/ECONNREFUSED/i.test(err.toString())) {
|
|
this._onWorkerWindowUnavailable()
|
|
} else {
|
|
err.message = `Error checking sync health: ${err.message}`
|
|
NylasEnv.reportError(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
_onWorkerWindowUnavailable() {
|
|
let extraData = {};
|
|
|
|
// Extract data that we want to report. We'll report the entire
|
|
// _lastSyncActivity object, but it'll probably be useful if we can segment
|
|
// by the data in the oldest or newest entry, so we report those as
|
|
// individual values too.
|
|
const lastActivityEntries = Object.entries(this._lastSyncActivity || {})
|
|
if (lastActivityEntries.length > 0) {
|
|
const times = lastActivityEntries.map((entry) => entry[1].time)
|
|
const now = Date.now()
|
|
|
|
const maxTime = Math.max(...times)
|
|
const mostRecentEntry = lastActivityEntries.find((entry) => entry[1].time === maxTime)
|
|
const [mostRecentActivityAccountId, {
|
|
activity: mostRecentActivity,
|
|
time: mostRecentActivityTime,
|
|
}] = mostRecentEntry;
|
|
const mostRecentDuration = now - mostRecentActivityTime
|
|
|
|
const minTime = Math.min(...times)
|
|
const leastRecentEntry = lastActivityEntries.find((entry) => entry[1].time === minTime)
|
|
const [leastRecentActivityAccountId, {
|
|
activity: leastRecentActivity,
|
|
time: leastRecentActivityTime,
|
|
}] = leastRecentEntry;
|
|
const leastRecentDuration = now - leastRecentActivityTime
|
|
|
|
extraData = {
|
|
mostRecentActivity,
|
|
mostRecentActivityTime,
|
|
mostRecentActivityAccountId,
|
|
mostRecentDuration,
|
|
leastRecentActivity,
|
|
leastRecentActivityTime,
|
|
leastRecentActivityAccountId,
|
|
leastRecentDuration,
|
|
}
|
|
}
|
|
|
|
NylasEnv.reportError(new Error('Worker window was unavailable'), {
|
|
// This information isn't as useful in Sentry, but include it here until
|
|
// the data is actually sent to Mixpanel. (See the TODO below)
|
|
lastActivityPerAccount: this._lastSyncActivity,
|
|
...extraData,
|
|
})
|
|
|
|
// TODO: This doesn't make it to Mixpanel because our analytics process
|
|
// lives in the worker window. We should move analytics to the main process.
|
|
// https://phab.nylas.com/T8029
|
|
Actions.recordUserEvent('Worker Window Unavailable', {
|
|
lastActivityPerAccount: this._lastSyncActivity,
|
|
...extraData,
|
|
})
|
|
|
|
console.log(`Detected worker window was unavailable. Restarting it.`, this._lastSyncActivity)
|
|
ipcRenderer.send('ensure-worker-window')
|
|
}
|
|
}
|
|
|
|
export default new SyncHealthChecker()
|