From 320b37fb4d01ef31cb150a99d01158fd46a12494 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 29 Aug 2017 13:55:32 -0700 Subject: [PATCH] =?UTF-8?q?Implement=20=E2=80=9Csync=20now=20concept?= =?UTF-8?q?=E2=80=9D=20in=20C++,=20trigger=20=E2=80=9Csync=20now=E2=80=9D?= =?UTF-8?q?=20when=20coming=20back=20online?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/menus/darwin.json | 2 + app/menus/linux.json | 2 + app/menus/win32.json | 2 + app/src/flux/mailsync-bridge.es6 | 15 +++ app/src/flux/stores/online-status-store.es6 | 109 ++++++-------------- app/src/window-event-handler.es6 | 4 + mailsync | 2 +- 7 files changed, 60 insertions(+), 76 deletions(-) diff --git a/app/menus/darwin.json b/app/menus/darwin.json index e23595780..732b00ca5 100644 --- a/app/menus/darwin.json +++ b/app/menus/darwin.json @@ -28,6 +28,8 @@ { "label": "File", "submenu": [ + { "label": "Sync New Mail Now", "command": "window:sync-mail-now" }, + { "type": "separator" }, { "label": "New Message", "command": "application:new-message" }, { "type": "separator" }, { "label": "Close Window", "command": "window:close" }, diff --git a/app/menus/linux.json b/app/menus/linux.json index bebd589dd..0eaea1afa 100644 --- a/app/menus/linux.json +++ b/app/menus/linux.json @@ -3,6 +3,8 @@ { "label": "&File", "submenu": [ + { "label": "Sync New Mail Now", "command": "window:sync-mail-now" }, + { "type": "separator" }, { "label": "&New Message...", "command": "application:new-message" }, { "type": "separator" }, { "label": "Add Account...", "command": "application:add-account", "args": {"source": "Menu"}}, diff --git a/app/menus/win32.json b/app/menus/win32.json index c53ab8490..142afebbe 100644 --- a/app/menus/win32.json +++ b/app/menus/win32.json @@ -79,6 +79,8 @@ "command": "application:view-help" }, { "type": "separator" }, + { "label": "Sync New Mail Now", "command": "window:sync-mail-now" }, + { "type": "separator" }, { "label": "Preferences", "command": "application:open-preferences" }, { "label": "Add Account...", "command": "application:add-account", "args": {"source": "Menu"}}, { "label": "Change Theme...", "command": "window:launch-theme-picker" }, diff --git a/app/src/flux/mailsync-bridge.es6 b/app/src/flux/mailsync-bridge.es6 index d13a25aec..785e58fd9 100644 --- a/app/src/flux/mailsync-bridge.es6 +++ b/app/src/flux/mailsync-bridge.es6 @@ -6,6 +6,7 @@ import TaskQueue from './stores/task-queue'; import IdentityStore from './stores/identity-store'; import AccountStore from './stores/account-store'; import DatabaseStore from './stores/database-store'; +import OnlineStatusStore from './stores/online-status-store'; import DatabaseChangeRecord from './stores/database-change-record'; import DatabaseObjectRegistry from '../registries/database-object-registry'; import MailsyncProcess from '../mailsync-process'; @@ -37,6 +38,7 @@ export default class MailsyncBridge { // }, this); AccountStore.listen(this.ensureClients, this); + OnlineStatusStore.listen(this.onOnlineStatusChanged, this); NylasEnv.onBeforeUnload(this.onBeforeUnload); process.nextTick(() => { @@ -173,6 +175,19 @@ export default class MailsyncBridge { return true; } + onOnlineStatusChanged = ({onlineDidChange}) => { + if (onlineDidChange && OnlineStatusStore.isOnline()) { + this.sendSyncMailNow(); + } + } + + sendSyncMailNow() { + console.warn("Sending `wake` to all mailsync workers..."); + for (const client of Object.values(this._clients)) { + client.sendMessage({type: "wake-workers"}); + } + } + sendMessageToAccount(accountId, json) { if (!this._clients[accountId]) { const err = new Error(`No mailsync worker is running.`); diff --git a/app/src/flux/stores/online-status-store.es6 b/app/src/flux/stores/online-status-store.es6 index e74d29a38..7c6f8ac13 100644 --- a/app/src/flux/stores/online-status-store.es6 +++ b/app/src/flux/stores/online-status-store.es6 @@ -4,111 +4,70 @@ import Actions from '../actions'; let isOnlineModule = null; -const CHECK_ONLINE_INTERVAL = 30 * 1000 +const CHECK_ONLINE_INTERVAL = 30 * 1000; class OnlineStatusStore extends NylasStore { constructor() { super() - this._isOnline = true - this._retryingInSeconds = 0 - this._countdownInterval = null - this._checkOnlineTimeout = null - this._backoffScheduler = new ExponentialBackoffScheduler({jitter: false}) + this._online = true; + this._countdownSeconds = 0; - this.setupEmitter() + this._interval = null; + this._timeout = null; + this._backoffScheduler = new ExponentialBackoffScheduler({jitter: false}); if (NylasEnv.isMainWindow()) { - Actions.checkOnlineStatus.listen(() => this._checkOnlineStatus()); - setTimeout(() => { - this._checkOnlineStatus(); - }, 3000); + Actions.checkOnlineStatus.listen(this._checkOnlineStatus); + setTimeout(this._checkOnlineStatus, 3 * 1000); // initial check } } isOnline() { - return this._isOnline + return this._online; } retryingInSeconds() { - return this._retryingInSeconds + return this._countdownSeconds; } async _setNextOnlineState() { isOnlineModule = isOnlineModule || require('is-online'); //eslint-disable-line const nextIsOnline = await isOnlineModule(); - if (this._isOnline !== nextIsOnline) { - this._isOnline = nextIsOnline - this.trigger() + if (this._online !== nextIsOnline) { + this._online = nextIsOnline + this.trigger({onlineDidChange: true, countdownDidChange: false}) } } - async _checkOnlineStatus() { - this._clearCheckOnlineInterval() - this._clearRetryCountdown() + _checkOnlineStatus = async () => { + clearInterval(this._interval); + clearTimeout(this._timeout); - // If we are currently offline, this trigger will show the `Retrying now...` - // message - this._retryingInSeconds = 0 - this.trigger() + // If we are currently offline, this trigger will show `Retrying now...` + this._countdownSeconds = 0 + this.trigger({onlineDidChange: false, countdownDidChange: true}); await this._setNextOnlineState() - if (!this._isOnline) { - this._checkOnlineStatusAfterBackoff() + if (this._online) { + // just check again later + this._backoffScheduler.reset(); + this._timeout = setTimeout(this._checkOnlineStatus, CHECK_ONLINE_INTERVAL); + } else { - this._backoffScheduler.reset() - this._checkOnlineTimeout = setTimeout(() => { - this._checkOnlineStatus() - }, CHECK_ONLINE_INTERVAL) - } - } - - async _checkOnlineStatusAfterBackoff() { - const nextDelayMs = this._backoffScheduler.nextDelay() - try { - await this._countdownRetryingInSeconds(nextDelayMs) - this._checkOnlineStatus() - } catch (err) { - // This means the retry countdown was cleared, in which case we don't - // want to do anything - } - } - - async _countdownRetryingInSeconds(nextDelayMs) { - this._retryingInSeconds = Math.ceil(nextDelayMs / 1000) - this.trigger() - - return new Promise((resolve, reject) => { - this._clearRetryCountdown() - this._emitter.once('clear-retry-countdown', () => reject(new Error('Retry countdown cleared'))) - - this._countdownInterval = setInterval(() => { - this._retryingInSeconds = Math.max(0, this._retryingInSeconds - 1) - this.trigger() - - if (this._retryingInSeconds === 0) { - this._clearCountdownInterval() - resolve() + // count down an inreasing delay and check again + this._countdownSeconds = Math.ceil(this._backoffScheduler.nextDelay() / 1000); + this._interval = setInterval(() => { + this._countdownSeconds = Math.max(0, this._countdownSeconds - 1); + if (this._countdownSeconds === 0) { + this._checkOnlineStatus(); + } else { + this.trigger({onlineDidChange: false, countdownDidChange: true}); } - }, 1000) - }) - } - - _clearCheckOnlineInterval() { - clearInterval(this._checkOnlineTimeout) - this._checkOnlineTimeout = null - } - - _clearCountdownInterval() { - clearInterval(this._countdownInterval) - this._countdownInterval = null - } - - _clearRetryCountdown() { - this._clearCountdownInterval() - this._emitter.emit('clear-retry-countdown') + }, 1000); + } } } diff --git a/app/src/window-event-handler.es6 b/app/src/window-event-handler.es6 index dfe9c583c..dd52e8286 100644 --- a/app/src/window-event-handler.es6 +++ b/app/src/window-event-handler.es6 @@ -79,6 +79,10 @@ export default class WindowEventHandler { NylasEnv.mailsyncBridge.openLogs(); }); + NylasEnv.commands.add(document.body, 'window:sync-mail-now', () => { + NylasEnv.mailsyncBridge.sendSyncMailNow(); + }); + NylasEnv.commands.add(document.body, 'window:attach-to-xcode', () => { const client = Object.values(NylasEnv.mailsyncBridge.clients()).pop(); if (client) { diff --git a/mailsync b/mailsync index 76ad51ec5..17f139ca4 160000 --- a/mailsync +++ b/mailsync @@ -1 +1 @@ -Subproject commit 76ad51ec511685bada33583ebc7b3e33b5db71a9 +Subproject commit 17f139ca4b015835d0ae478d18e6b6c0fae780d5