From 6c65b0db09e800a849293d7b2c4bc07fa5c56058 Mon Sep 17 00:00:00 2001 From: Djorkaeff Alexandre Date: Fri, 3 Apr 2020 10:53:39 -0300 Subject: [PATCH 1/6] [IMPROVEMENT] Change server while connecting --- app/lib/rocketchat.js | 18 ++++++++++++++++-- app/sagas/selectServer.js | 16 ++-------------- app/views/RoomsListView/Header/Header.ios.js | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 1604880af2..963972df32 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -49,6 +49,7 @@ import { SERVERS, SERVER_URL } from '../constants/userDefaults'; import { setActiveUsers } from '../actions/activeUsers'; import I18n from '../i18n'; import { twoFactor } from '../utils/twoFactor'; +import { selectServerFailure } from '../actions/server'; const TOKEN_KEY = 'reactnativemeteor_usertoken'; const SORT_PREFS_KEY = 'RC_SORT_PREFS_KEY'; @@ -113,6 +114,14 @@ const RocketChat = { }; }, async getServerInfo(server) { + if (this.controller) { + this.controller.abort(); + this.controller = null; + } + + this.controller = new AbortController(); + const { signal } = this.controller; + const notRCServer = { success: false, message: 'Not_RC_Server', @@ -121,7 +130,7 @@ const RocketChat = { } }; try { - const result = await fetch(`${ server }/api/info`).then(async(response) => { + const result = await fetch(`${ server }/api/info`, { signal }).then(async(response) => { let res = notRCServer; try { res = await response.json(); @@ -147,6 +156,10 @@ const RocketChat = { } return result; } catch (e) { + if (e.message === 'Aborted') { + reduxStore.dispatch(selectServerFailure()); + throw e; + } log(e); } return { @@ -208,7 +221,8 @@ const RocketChat = { this.sdk.connect() .then(() => { - if (user && user.token) { + const { server: currentServer } = reduxStore.getState().server; + if (user && user.token && server === currentServer) { reduxStore.dispatch(loginRequest({ resume: user.token }, logoutOnError)); } }) diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index 23a716bc6f..afb4857e0d 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -1,6 +1,4 @@ -import { - put, take, takeLatest, fork, cancel, race -} from 'redux-saga/effects'; +import { put, takeLatest } from 'redux-saga/effects'; import { Alert } from 'react-native'; import RNUserDefaults from 'rn-user-defaults'; import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; @@ -150,16 +148,6 @@ const handleServerRequest = function* handleServerRequest({ server, certificate const root = function* root() { yield takeLatest(SERVER.REQUEST, handleServerRequest); - - while (true) { - const params = yield take(SERVER.SELECT_REQUEST); - const selectServerTask = yield fork(handleSelectServer, params); - yield race({ - request: take(SERVER.SELECT_REQUEST), - success: take(SERVER.SELECT_SUCCESS), - failure: take(SERVER.SELECT_FAILURE) - }); - yield cancel(selectServerTask); - } + yield takeLatest(SERVER.SELECT_REQUEST, handleSelectServer); }; export default root; diff --git a/app/views/RoomsListView/Header/Header.ios.js b/app/views/RoomsListView/Header/Header.ios.js index 31f887cf57..35a8a65d91 100644 --- a/app/views/RoomsListView/Header/Header.ios.js +++ b/app/views/RoomsListView/Header/Header.ios.js @@ -56,7 +56,7 @@ const Header = React.memo(({ onPress={onPress} testID='rooms-list-header-server-dropdown-button' style={styles.container} - disabled={connecting || isFetching} + // disabled={connecting || isFetching} > From 7c4d993b13357334d2bbb4d4b1ca6704410cbd01 Mon Sep 17 00:00:00 2001 From: Djorkaeff Alexandre Date: Fri, 3 Apr 2020 11:01:03 -0300 Subject: [PATCH 2/6] [FIX] Not login/reconnect to previous server --- app/lib/rocketchat.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 963972df32..acf9fa3cd7 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -229,10 +229,13 @@ const RocketChat = { .catch((err) => { console.log('connect error', err); - // when `connect` raises an error, we try again in 10 seconds - this.connectTimeout = setTimeout(() => { - this.connect({ server, user }); - }, 10000); + const { server: currentServer } = reduxStore.getState().server; + if (server === currentServer) { + // when `connect` raises an error, we try again in 10 seconds + this.connectTimeout = setTimeout(() => { + this.connect({ server, user }); + }, 10000); + } }); this.connectedListener = this.sdk.onStreamData('connected', () => { From 6a90d3e79d61398817198ddf9eee840fcc6e9f36 Mon Sep 17 00:00:00 2001 From: Djorkaeff Alexandre Date: Fri, 3 Apr 2020 11:24:17 -0300 Subject: [PATCH 3/6] [FIX] Abort all fetch while connecting --- app/lib/rocketchat.js | 10 +--------- app/sagas/selectServer.js | 6 ++++++ app/utils/fetch.js | 5 +++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index acf9fa3cd7..bb40bc77d3 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -114,14 +114,6 @@ const RocketChat = { }; }, async getServerInfo(server) { - if (this.controller) { - this.controller.abort(); - this.controller = null; - } - - this.controller = new AbortController(); - const { signal } = this.controller; - const notRCServer = { success: false, message: 'Not_RC_Server', @@ -130,7 +122,7 @@ const RocketChat = { } }; try { - const result = await fetch(`${ server }/api/info`, { signal }).then(async(response) => { + const result = await fetch(`${ server }/api/info`).then(async(response) => { let res = notRCServer; try { res = await response.json(); diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index afb4857e0d..b135ef70d2 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -95,6 +95,12 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch yield put(clearSettings()); + if (RocketChat.controller) { + RocketChat.controller.abort(); + } + + RocketChat.controller = new AbortController(); + if (user) { yield RocketChat.connect({ server, user, logoutOnError: true }); yield put(setUser(user)); diff --git a/app/utils/fetch.js b/app/utils/fetch.js index 7b0fae135f..a804e0a128 100644 --- a/app/utils/fetch.js +++ b/app/utils/fetch.js @@ -1,6 +1,7 @@ import { Platform } from 'react-native'; import DeviceInfo from 'react-native-device-info'; import { settings as RocketChatSettings } from '@rocket.chat/sdk'; +import RocketChat from '../lib/rocketchat'; // this form is required by Rocket.Chat's parser in "app/statistics/server/lib/UAParserCustom.js" export const headers = { @@ -25,5 +26,9 @@ export default (url, options = {}) => { if (options && options.headers) { customOptions = { ...customOptions, headers: { ...options.headers, ...customOptions.headers } }; } + if (RocketChat.controller) { + const { signal } = RocketChat.controller; + customOptions = { ...customOptions, signal }; + } return fetch(url, customOptions); }; From e35008f1dd5b793b88cc15c6a3b25fa17d43f025 Mon Sep 17 00:00:00 2001 From: Djorkaeff Alexandre Date: Fri, 3 Apr 2020 12:35:43 -0300 Subject: [PATCH 4/6] [FIX] Abort sdk fetch --- app/lib/rocketchat.js | 9 +++ app/sagas/selectServer.js | 6 +- patches/@rocket.chat+sdk+1.0.0-alpha.41.patch | 76 ++++++++++++++++++- 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index bb40bc77d3..a49a61d135 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -165,6 +165,15 @@ const RocketChat = { stopListener(listener) { return listener && listener.stop(); }, + abort() { + if (this.controller) { + this.controller.abort(); + if (this.sdk) { + this.sdk.abort(); + } + } + this.controller = new AbortController(); + }, connect({ server, user, logoutOnError = false }) { return new Promise((resolve) => { if (!this.sdk || this.sdk.client.host !== server) { diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index b135ef70d2..3f28794aeb 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -95,11 +95,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch yield put(clearSettings()); - if (RocketChat.controller) { - RocketChat.controller.abort(); - } - - RocketChat.controller = new AbortController(); + RocketChat.abort(); if (user) { yield RocketChat.connect({ server, user, logoutOnError: true }); diff --git a/patches/@rocket.chat+sdk+1.0.0-alpha.41.patch b/patches/@rocket.chat+sdk+1.0.0-alpha.41.patch index 9dfff7688e..5aa3f3aa40 100644 --- a/patches/@rocket.chat+sdk+1.0.0-alpha.41.patch +++ b/patches/@rocket.chat+sdk+1.0.0-alpha.41.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/@rocket.chat/sdk/lib/api/api.js b/node_modules/@rocket.chat/sdk/lib/api/api.js -index 5b7dc21..49f1af5 100644 +index 5b7dc21..fa3c18d 100644 --- a/node_modules/@rocket.chat/sdk/lib/api/api.js +++ b/node_modules/@rocket.chat/sdk/lib/api/api.js @@ -62,6 +62,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); @@ -19,8 +19,80 @@ index 5b7dc21..49f1af5 100644 }, set: function (obj) { this._headers = obj; +@@ -88,31 +89,38 @@ var Client = /** @class */ (function () { + data : + JSON.stringify(data); + }; ++ Client.prototype.getSignal = function (options) { ++ return options && options.signal; ++ } + Client.prototype.get = function (url, data, options) { + return fetch(this.host + "/api/v1/" + encodeURI(url) + "?" + this.getParams(data), { + method: 'GET', +- headers: this.getHeaders(options) ++ headers: this.getHeaders(options), ++ signal: this.getSignal(options) + }).then(this.handle); + }; + Client.prototype.post = function (url, data, options) { + return fetch(this.host + "/api/v1/" + encodeURI(url), { + method: 'POST', + body: this.getBody(data), +- headers: this.getHeaders(options) ++ headers: this.getHeaders(options), ++ signal: this.getSignal(options) + }).then(this.handle); + }; + Client.prototype.put = function (url, data, options) { + return fetch(this.host + "/api/v1/" + encodeURI(url), { + method: 'PUT', + body: this.getBody(data), +- headers: this.getHeaders(options) ++ headers: this.getHeaders(options), ++ signal: this.getSignal(options) + }).then(this.handle); + }; + Client.prototype.delete = function (url, data, options) { + return fetch(this.host + "/api/v1/" + encodeURI(url), { + method: 'DELETE', + body: this.getBody(data), +- headers: this.getHeaders(options) ++ headers: this.getHeaders(options), ++ signal: this.getSignal(options) + }).then(this.handle); + }; + Client.prototype.handle = function (r) { +@@ -149,6 +157,7 @@ var Api = /** @class */ (function (_super) { + var _this = _super.call(this) || this; + _this.userId = ''; + _this.currentLogin = null; ++ _this.controller = new AbortController(); + /** + * Do a request to an API endpoint. + * If it needs a token, login first (with defaults) to set auth headers. +@@ -173,6 +182,10 @@ var Api = /** @class */ (function (_super) { + if (auth && !this.loggedIn()) { + throw new Error(''); + } ++ ++ const { signal } = this.controller; ++ options = { ...options, signal }; ++ + result = void 0; + _a = method; + switch (_a) { +@@ -235,6 +248,9 @@ var Api = /** @class */ (function (_super) { + if (options === void 0) { options = {}; } + return _this.request('DELETE', endpoint, data, auth, ignore, options); + }; ++ _this.abort = function () { ++ return _this.controller.abort(); ++ } + _this.client = client || new Client({ host: host }); + _this.logger = log_1.logger; + return _this; diff --git a/node_modules/@rocket.chat/sdk/lib/drivers/ddp.js b/node_modules/@rocket.chat/sdk/lib/drivers/ddp.js -index e3510c7..e3216cc 100644 +index 8f04ff1..e3216cc 100644 --- a/node_modules/@rocket.chat/sdk/lib/drivers/ddp.js +++ b/node_modules/@rocket.chat/sdk/lib/drivers/ddp.js @@ -110,6 +110,7 @@ tiny_events_1.EventEmitter.prototype.removeAllListeners = function (event) { From 138321d93960ca807327b0059564c5924b67ebbc Mon Sep 17 00:00:00 2001 From: Djorkaeff Alexandre Date: Fri, 3 Apr 2020 12:42:01 -0300 Subject: [PATCH 5/6] [FIX] Patch-package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5894e508b5..ffd757f147 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "react-native-responsive-ui": "^1.1.1", "react-native-screens": "^2.0.0-alpha.3", "react-native-scrollable-tab-view": "^1.0.0", - "react-native-slowlog": "^1.0.2", + "react-native-slowlog": "1.0.2", "react-native-unimodules": "0.5.3", "react-native-vector-icons": "6.6.0", "react-native-video": "5.0.2", From a84b6d2dfd5cf149684c868a375bbddd6e7ce3fc Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Tue, 5 May 2020 10:02:08 -0300 Subject: [PATCH 6/6] Add comments --- app/lib/rocketchat.js | 1 + app/sagas/selectServer.js | 1 + 2 files changed, 2 insertions(+) diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index cfafbe6894..80fd29727e 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -160,6 +160,7 @@ const RocketChat = { stopListener(listener) { return listener && listener.stop(); }, + // Abort all requests and create a new AbortController abort() { if (this.controller) { this.controller.abort(); diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index bbe06c48f0..7596e05d12 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -96,6 +96,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch const basicAuth = yield RNUserDefaults.get(`${ BASIC_AUTH_KEY }-${ server }`); setBasicAuth(basicAuth); + // Check for running requests and abort them before connecting to the server RocketChat.abort(); if (user) {