mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-10 06:34:40 +08:00
Fix error handling on connection close
This commit is contained in:
parent
016bad67b9
commit
14b5bef0a7
2 changed files with 49 additions and 34 deletions
|
@ -4,6 +4,14 @@ const _ = require('underscore');
|
|||
const xoauth2 = require('xoauth2');
|
||||
const EventEmitter = require('events');
|
||||
|
||||
class IMAPConnectionNotReadyError extends Error {
|
||||
constructor(funcName) {
|
||||
super(`${funcName} - You must call connect() first.`);
|
||||
|
||||
// hack so that the error matches the ones used by node-imap
|
||||
this.source = 'socket';
|
||||
}
|
||||
}
|
||||
|
||||
class IMAPBox {
|
||||
|
||||
|
@ -123,28 +131,28 @@ class IMAPBox {
|
|||
|
||||
addFlags(range, flags) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPBox::addFlags - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPBox::addFlags`)
|
||||
}
|
||||
return this._imap.addFlagsAsync(range, flags)
|
||||
}
|
||||
|
||||
delFlags(range, flags) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPBox::delFlags - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPBox::delFlags`)
|
||||
}
|
||||
return this._imap.delFlagsAsync(range, flags)
|
||||
}
|
||||
|
||||
moveFromBox(range, folderName) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPBox::moveFromBox - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPBox::moveFromBox`)
|
||||
}
|
||||
return this._imap.moveAsync(range, folderName)
|
||||
}
|
||||
|
||||
closeBox({expunge = true} = {}) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPBox::closeBox - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPBox::closeBox`)
|
||||
}
|
||||
return this._imap.closeBoxAsync(expunge)
|
||||
}
|
||||
|
@ -174,7 +182,8 @@ class IMAPConnection extends EventEmitter {
|
|||
this._queue = [];
|
||||
this._currentOperation = null;
|
||||
this._settings = settings;
|
||||
this._imap = null
|
||||
this._imap = null;
|
||||
this._connectPromise = null;
|
||||
}
|
||||
|
||||
connect() {
|
||||
|
@ -222,7 +231,9 @@ class IMAPConnection extends EventEmitter {
|
|||
this._imap = Promise.promisifyAll(new Imap(settings));
|
||||
|
||||
this._imap.once('end', () => {
|
||||
console.log('Connection ended');
|
||||
console.log('Underlying IMAP Connection ended');
|
||||
this._connectPromise = null;
|
||||
this._imap = null;
|
||||
});
|
||||
|
||||
this._imap.on('alert', (msg) => {
|
||||
|
@ -255,11 +266,12 @@ class IMAPConnection extends EventEmitter {
|
|||
this._queue = [];
|
||||
this._imap.end();
|
||||
this._imap = null;
|
||||
this._connectPromise = null;
|
||||
}
|
||||
|
||||
serverSupports(capability) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPConnection::serverSupports - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPConnection::serverSupports`)
|
||||
}
|
||||
this._imap.serverSupports(capability);
|
||||
}
|
||||
|
@ -269,7 +281,7 @@ class IMAPConnection extends EventEmitter {
|
|||
*/
|
||||
openBox(folderName, {readOnly = false} = {}) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPConnection::openBox - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPConnection::openBox`)
|
||||
}
|
||||
return this._imap.openBoxAsync(folderName, readOnly).then((box) =>
|
||||
new IMAPBox(this._imap, box)
|
||||
|
@ -278,35 +290,35 @@ class IMAPConnection extends EventEmitter {
|
|||
|
||||
getBoxes() {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPConnection::getBoxes - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPConnection::getBoxes`)
|
||||
}
|
||||
return this._imap.getBoxesAsync()
|
||||
}
|
||||
|
||||
addBox(folderName) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPConnection::addBox - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPConnection::addBox`)
|
||||
}
|
||||
return this._imap.addBoxAsync(folderName)
|
||||
}
|
||||
|
||||
renameBox(oldFolderName, newFolderName) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPConnection::renameBox - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPConnection::renameBox`)
|
||||
}
|
||||
return this._imap.renameBoxAsync(oldFolderName, newFolderName)
|
||||
}
|
||||
|
||||
delBox(folderName) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPConnection::delBox - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPConnection::delBox`)
|
||||
}
|
||||
return this._imap.delBoxAsync(folderName)
|
||||
}
|
||||
|
||||
runOperation(operation) {
|
||||
if (!this._imap) {
|
||||
throw new Error(`IMAPConnection::runOperation - You need to call connect() first.`)
|
||||
throw new IMAPConnectionNotReadyError(`IMAPConnection::runOperation`)
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._queue.push({operation, resolve, reject});
|
||||
|
@ -317,11 +329,13 @@ class IMAPConnection extends EventEmitter {
|
|||
}
|
||||
|
||||
processNextOperation() {
|
||||
if (this._currentOperation) { return }
|
||||
if (this._currentOperation) {
|
||||
return;
|
||||
}
|
||||
this._currentOperation = this._queue.shift();
|
||||
if (!this._currentOperation) {
|
||||
this.emit('queue-empty');
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const {operation, resolve, reject} = this._currentOperation;
|
||||
|
@ -329,8 +343,8 @@ class IMAPConnection extends EventEmitter {
|
|||
if (result instanceof Promise === false) {
|
||||
reject(new Error(`Expected ${operation.constructor.name} to return promise.`))
|
||||
}
|
||||
result
|
||||
.then(() => {
|
||||
|
||||
result.then(() => {
|
||||
this._currentOperation = null;
|
||||
console.log(`Finished task: ${operation.description()}`)
|
||||
resolve();
|
||||
|
@ -344,6 +358,6 @@ class IMAPConnection extends EventEmitter {
|
|||
})
|
||||
}
|
||||
}
|
||||
IMAPConnection.Capabilities = Capabilities;
|
||||
|
||||
IMAPConnection.Capabilities = Capabilities;
|
||||
module.exports = IMAPConnection
|
||||
|
|
|
@ -45,7 +45,6 @@ class SyncWorker {
|
|||
if (this._conn) {
|
||||
this._conn.end();
|
||||
}
|
||||
this._conn = null
|
||||
}
|
||||
|
||||
_onMessage(msg) {
|
||||
|
@ -61,15 +60,19 @@ class SyncWorker {
|
|||
}
|
||||
|
||||
_onAccountUpdated() {
|
||||
if (this.isNextSyncScheduled()) {
|
||||
this._getAccount().then((account) => {
|
||||
this._account = account;
|
||||
this.syncNow({reason: 'Account Modification'});
|
||||
});
|
||||
if (!this.isWaitingForNextSync()) {
|
||||
return;
|
||||
}
|
||||
this._getAccount().then((account) => {
|
||||
this._account = account;
|
||||
this.syncNow({reason: 'Account Modification'});
|
||||
});
|
||||
}
|
||||
|
||||
_onConnectionIdleUpdate() {
|
||||
if (!this.isWaitingForNextSync()) {
|
||||
return;
|
||||
}
|
||||
this.syncNow({reason: 'IMAP IDLE Fired'});
|
||||
}
|
||||
|
||||
|
@ -127,7 +130,8 @@ class SyncWorker {
|
|||
.catch((error) => {
|
||||
syncbackRequest.error = error
|
||||
syncbackRequest.status = "FAILED"
|
||||
}).finally(() => syncbackRequest.save())
|
||||
})
|
||||
.finally(() => syncbackRequest.save())
|
||||
}
|
||||
|
||||
syncAllCategories() {
|
||||
|
@ -146,12 +150,6 @@ class SyncWorker {
|
|||
});
|
||||
}
|
||||
|
||||
performSync() {
|
||||
return this.syncbackMessageActions()
|
||||
.then(() => this._conn.runOperation(new FetchFolderList(this._account.provider)))
|
||||
.then(() => this.syncAllCategories())
|
||||
}
|
||||
|
||||
syncNow({reason} = {}) {
|
||||
clearTimeout(this._syncTimer);
|
||||
this._syncTimer = null;
|
||||
|
@ -164,7 +162,9 @@ class SyncWorker {
|
|||
|
||||
this.ensureConnection()
|
||||
.then(() => this._account.update({syncError: null}))
|
||||
.then(() => this.performSync())
|
||||
.then(() => this.syncbackMessageActions())
|
||||
.then(() => this._conn.runOperation(new FetchFolderList(this._account.provider)))
|
||||
.then(() => this.syncAllCategories())
|
||||
.then(() => this.onSyncDidComplete())
|
||||
.catch((error) => this.onSyncError(error))
|
||||
.finally(() => {
|
||||
|
@ -177,10 +177,11 @@ class SyncWorker {
|
|||
console.error(`SyncWorker: Error while syncing account ${this._account.emailAddress} (${this._account.id})`, error)
|
||||
this.closeConnection()
|
||||
|
||||
if (error.source === 'socket') {
|
||||
if (error.source.includes('socket') || error.source.includes('timeout')) {
|
||||
// Continue to retry if it was a network error
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
this._account.syncError = jsonError(error)
|
||||
return this._account.save()
|
||||
}
|
||||
|
@ -219,7 +220,7 @@ class SyncWorker {
|
|||
throw new Error(`SyncWorker.onSyncDidComplete: Unknown afterSync behavior: ${afterSync}. Closing connection`)
|
||||
}
|
||||
|
||||
isNextSyncScheduled() {
|
||||
isWaitingForNextSync() {
|
||||
return this._syncTimer != null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue