mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-12 04:25:31 +08:00
112 lines
3.5 KiB
Text
112 lines
3.5 KiB
Text
|
import {ipcRenderer} from 'electron'
|
||
|
import {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 {
|
||
|
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()
|