[client-sync] Report latest sync activity

Summary:
Add infrastructure to report and retrieve the latest sync activity, and
start reporting when we download a message or detect that a folder
has no new messages. This will be used to detect if the sync loop is
stuck. Part of T7681.

Test Plan: manual, specs

Reviewers: evan, mark, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D4261
This commit is contained in:
Halla Moore 2017-03-27 15:32:11 -07:00
parent 7355527397
commit b6887e386e
4 changed files with 89 additions and 3 deletions

View file

@ -0,0 +1,52 @@
const Joi = require('joi');
const {getLastSyncActivityForAccount, getLastSyncActivity} = require('../../shared/sync-activity').default
module.exports = (server) => {
server.route({
method: 'GET',
path: '/health',
config: {
description: 'Returns information about the last recorded sync activity for all accounts',
tags: ['health'],
},
handler: (request, reply) => {
let response;
try {
response = getLastSyncActivity()
response = JSON.stringify(response)
reply(response)
} catch (err) {
const context = response ? "" : "Could not retrieve last sync activity"
request.logger.error(err, context)
reply(err)
}
},
})
server.route({
method: 'GET',
path: '/health/{accountId}',
config: {
description: 'Returns information about the last recorded sync activity for the specified account',
tags: ['health'],
validate: {
params: {
accountId: Joi.string(),
},
},
},
handler: (request, reply) => {
let response;
try {
const {accountId} = request.params
response = getLastSyncActivityForAccount(accountId)
response = JSON.stringify(response)
reply(response)
} catch (err) {
const context = response ? "" : "Could not retrieve last sync activity"
request.logger.error(err, context)
reply(err)
}
},
})
};

View file

@ -3,6 +3,7 @@ const {IMAPConnection} = require('isomorphic-core');
const {Capabilities} = IMAPConnection;
const SyncTask = require('./sync-task')
const MessageProcessor = require('../../message-processor')
const {reportSyncActivity} = require('../../shared/sync-activity').default
const MessageFlagAttributes = ['id', 'threadId', 'folderImapUID', 'unread', 'starred', 'folderImapXGMLabels']
const FETCH_ATTRIBUTES_BATCH_SIZE = 1000;
@ -724,7 +725,9 @@ class FetchMessagesInFolderIMAP extends SyncTask {
if (shouldFetchMessages) {
yield this._fetchNextMessageBatch()
} else {
this._logger.log(`🔚 📂 ${this._folder.name} has no new messages - skipping fetch messages`)
const activity = `🔚 📂 ${this._folder.name} has no new messages - skipping fetch messages`
this._logger.log(activity)
reportSyncActivity(this._db.accountId, activity)
}
if (shouldFetchAttributes) {
yield this._fetchMessageAttributeChanges();

View file

@ -9,6 +9,7 @@ const extractContacts = require('./extract-contacts');
const {MessageFactory} = require('isomorphic-core');
const LocalDatabaseConnector = require('../shared/local-database-connector');
const {BatteryStatusManager} = require('nylas-exports');
const {reportSyncActivity} = require('../shared/sync-activity');
const MAX_QUEUE_LENGTH = 500
const MAX_CPU_USE_ON_AC = 1.0;
@ -153,8 +154,9 @@ class MessageProcessor {
await folder.updateSyncState({oldestProcessedDate: justProcessedDate})
}
logger.log(`🔃 ✉️ (${folder.name}) "${messageValues.subject}" - ${messageValues.date}`)
const activity = `🔃 ✉️ (${folder.name}) "${messageValues.subject}" - ${messageValues.date}`
logger.log(activity)
reportSyncActivity(accountId, activity)
return processedMessage
} catch (err) {
await this._onError({imapMessage, desiredParts, folder, err, logger});

View file

@ -0,0 +1,29 @@
class SyncActivity {
constructor() {
// Keyed by accountId, each value is structured like
// {
// time: 1490293620249,
// activity: (whatever was passed in, usually a string)
// }
this._lastActivityByAccountId = {}
}
reportSyncActivity = (accountId, activity) => {
if (!this._lastActivityByAccountId[accountId]) {
this._lastActivityByAccountId[accountId] = {};
}
const lastActivity = this._lastActivityByAccountId[accountId]
lastActivity.time = Date.now();
lastActivity.activity = activity;
}
getLastSyncActivityForAccount = (accountId) => {
return this._lastActivityByAccountId[accountId]
}
getLastSyncActivity = () => {
return this._lastActivityByAccountId
}
}
export default new SyncActivity()