Fix missing promise based error handling in sync-worker

This commit is contained in:
Juan Tejada 2016-06-26 09:52:03 -07:00
parent dd350a5081
commit 63b929e59b
3 changed files with 27 additions and 22 deletions

View file

@ -166,7 +166,7 @@ class IMAPConnection extends EventEmitter {
if (this._settings.refresh_token) { if (this._settings.refresh_token) {
const xoauthFields = ['client_id', 'client_secret', 'imap_username', 'refresh_token']; const xoauthFields = ['client_id', 'client_secret', 'imap_username', 'refresh_token'];
if (Object.keys(_.pick(this._settings, xoauthFields)).length !== 4) { if (Object.keys(_.pick(this._settings, xoauthFields)).length !== 4) {
throw new Error(`IMAPConnection: Expected ${xoauthFields.join(',')} when given refresh_token`) return Promise.reject(new Error(`IMAPConnection: Expected ${xoauthFields.join(',')} when given refresh_token`))
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
xoauth2.createXOAuth2Generator({ xoauth2.createXOAuth2Generator({
@ -223,6 +223,7 @@ class IMAPConnection extends EventEmitter {
end() { end() {
this._queue = []; this._queue = [];
this._imap.end(); this._imap.end();
this._imap = null;
} }
serverSupports(capability) { serverSupports(capability) {
@ -251,29 +252,30 @@ class IMAPConnection extends EventEmitter {
} }
processNextOperation() { processNextOperation() {
if (this._currentOperation) { return; } if (this._currentOperation) { return }
this._currentOperation = this._queue.shift(); this._currentOperation = this._queue.shift();
if (!this._currentOperation) { if (!this._currentOperation) {
this.emit('queue-empty'); this.emit('queue-empty');
return; return
} }
const {operation, resolve, reject} = this._currentOperation; const {operation, resolve, reject} = this._currentOperation;
console.log(`Starting task ${operation.description()}`) console.log(`Starting task ${operation.description()}`)
const result = operation.run(this._db, this); const result = operation.run(this._db, this);
if (result instanceof Promise === false) { if (result instanceof Promise === false) {
throw new Error(`Expected ${operation.constructor.name} to return promise.`); reject(new Error(`Expected ${operation.constructor.name} to return promise.`))
} }
result.catch((err) => { result
this._currentOperation = null;
console.error(err);
reject();
})
.then(() => { .then(() => {
this._currentOperation = null; this._currentOperation = null;
console.log(`Finished task ${operation.description()}`) console.log(`Finished task ${operation.description()}`)
resolve(); resolve();
}) })
.catch((err) => {
this._currentOperation = null;
console.error(err);
reject(err);
})
.finally(() => { .finally(() => {
this.processNextOperation(); this.processNextOperation();
}); });

View file

@ -114,6 +114,7 @@ class FetchMessagesInCategory {
_fetchMessagesAndQueueForProcessing(range) { _fetchMessagesAndQueueForProcessing(range) {
const messagesObservable = this._box.fetch(range) const messagesObservable = this._box.fetch(range)
// TODO Error handling here
messagesObservable.subscribe(this._processMessage.bind(this)) messagesObservable.subscribe(this._processMessage.bind(this))
return messagesObservable.toPromise() return messagesObservable.toPromise()
} }

View file

@ -22,9 +22,8 @@ class SyncWorker {
this.syncNow(); this.syncNow();
this._listener = PubsubConnector.observableForAccountChanges(account.id).subscribe(() => { this._listener = PubsubConnector.observableForAccountChanges(account.id)
this.onAccountChanged(); .subscribe(() => this.onAccountChanged())
});
} }
cleanup() { cleanup() {
@ -47,18 +46,19 @@ class SyncWorker {
const {afterSync} = this._account.syncPolicy; const {afterSync} = this._account.syncPolicy;
if (afterSync === 'idle') { if (afterSync === 'idle') {
this.getInboxCategory().then((inboxCategory) => { return this.getInboxCategory()
this._conn.openBox(inboxCategory.name, true).then(() => { .then((inboxCategory) => {
this._conn.openBox(inboxCategory.name).then(() => {
console.log("SyncWorker: - Idling on inbox category"); console.log("SyncWorker: - Idling on inbox category");
}); })
}); });
} else if (afterSync === 'close') { } else if (afterSync === 'close') {
console.log("SyncWorker: - Closing connection"); console.log("SyncWorker: - Closing connection");
this._conn.end(); this._conn.end();
this._conn = null; this._conn = null;
} else { return Promise.resolve()
throw new Error(`onSyncDidComplete: Unknown afterSync behavior: ${afterSync}`)
} }
return Promise.reject(new Error(`onSyncDidComplete: Unknown afterSync behavior: ${afterSync}`))
} }
onConnectionIdleUpdate() { onConnectionIdleUpdate() {
@ -73,15 +73,15 @@ class SyncWorker {
if (this._conn) { if (this._conn) {
return this._conn.connect(); return this._conn.connect();
} }
return new Promise((resolve) => { return new Promise((resolve, reject) => {
const settings = this._account.connectionSettings; const settings = this._account.connectionSettings;
const credentials = this._account.decryptedCredentials(); const credentials = this._account.decryptedCredentials();
if (!settings || !settings.imap_host) { if (!settings || !settings.imap_host) {
throw new Error("ensureConnection: There are no IMAP connection settings for this account.") return reject(new Error("ensureConnection: There are no IMAP connection settings for this account."))
} }
if (!credentials) { if (!credentials) {
throw new Error("ensureConnection: There are no IMAP connection credentials for this account.") return reject(new Error("ensureConnection: There are no IMAP connection credentials for this account."))
} }
const conn = new IMAPConnection(this._db, Object.assign({}, settings, credentials)); const conn = new IMAPConnection(this._db, Object.assign({}, settings, credentials));
@ -145,11 +145,13 @@ class SyncWorker {
.then(this.fetchCategoryList.bind(this)) .then(this.fetchCategoryList.bind(this))
.then(this.syncbackMessageActions.bind(this)) .then(this.syncbackMessageActions.bind(this))
.then(this.fetchMessagesInCategory.bind(this)) .then(this.fetchMessagesInCategory.bind(this))
// TODO Update account sync state in this error handler
.catch(console.error) .catch(console.error)
.finally(() => { .finally(() => {
this._lastSyncTime = Date.now() this._lastSyncTime = Date.now()
this.onSyncDidComplete(); this.onSyncDidComplete()
this.scheduleNextSync(); .catch((error) => console.error('SyncWorker.syncNow: Unhandled error while cleaning up sync: ', error))
.finally(() => this.scheduleNextSync())
}); });
} }