From 45a1ab3c765ec4838aea6b7524340326cfa9a06e Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 20:48:05 -0700 Subject: [PATCH 01/34] move global Vue reference to NetworkService --- src/services/AuthService.js | 4 +--- src/services/NetworkService.js | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/services/AuthService.js b/src/services/AuthService.js index a2dc0278..bbdc584a 100644 --- a/src/services/AuthService.js +++ b/src/services/AuthService.js @@ -1,7 +1,5 @@ import Validator from "validator"; -import Vue from "vue"; - import NetworkService from "./NetworkService"; import AnalyticsService from "./AnalyticsService"; @@ -125,7 +123,7 @@ export default { const authPromise = !context || isGlobal - ? NetworkService.userGlobal(Vue) + ? NetworkService.userGlobal() : NetworkService.user(context); return authPromise .then(res => { diff --git a/src/services/NetworkService.js b/src/services/NetworkService.js index 2cef19c5..6d171809 100644 --- a/src/services/NetworkService.js +++ b/src/services/NetworkService.js @@ -86,7 +86,7 @@ export default { .get(`${API_ROOT}/user`) .then(this._successHandler, this._errorHandler); }, - userGlobal(Vue) { + userGlobal() { return Vue.http .get(`${API_ROOT}/user`) .then(this._successHandler, this._errorHandler); From ceeaa61a19ae2d8aed519c1bdedec7e559e89a91 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 20:49:28 -0700 Subject: [PATCH 02/34] fault-tolerant session starting using promise-retry --- src/services/NetworkService.js | 54 +++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/src/services/NetworkService.js b/src/services/NetworkService.js index 6d171809..536bee84 100644 --- a/src/services/NetworkService.js +++ b/src/services/NetworkService.js @@ -1,10 +1,15 @@ import Vue from "vue"; +import promiseRetry from "promise-retry"; const AUTH_ROOT = `${process.env.VUE_APP_SERVER_ROOT}/auth`; const API_ROOT = `${process.env.VUE_APP_SERVER_ROOT}/api`; const ELIGIBILITY_API_ROOT = `${process.env.VUE_APP_SERVER_ROOT}/eligibility`; const CONTACT_API_ROOT = `${process.env.VUE_APP_SERVER_ROOT}/contact`; +const FAULT_TOLERANT_HTTP_TIMEOUT = 10000; +const FAULT_TOLERANT_HTTP_MAX_RETRY_TIMEOUT = 10000; +const FAULT_TOLERANT_HTTP_MAX_RETRIES = 10; + export default { _successHandler(res) { return Promise.resolve(res); @@ -12,6 +17,43 @@ export default { _errorHandler(res) { return Promise.reject(res); }, + _faultTolerantHttp(http, method, onRetry, url, data) { + const promise = + ["get", "delete", "head", "jsonp"].indexOf(method) !== -1 + ? http[method](url, { timeout: FAULT_TOLERANT_HTTP_TIMEOUT }).then( + this._successHandler, + this._errorHandler + ) + : http[method](url, data, { + timeout: FAULT_TOLERANT_HTTP_TIMEOUT + }).then(this._successHandler, this._errorHandler); + + return { + isAborted: false, + retryHttp: function() { + return promiseRetry( + retry => { + return promise.catch(res => { + if (res.status === 0 && !this.isAborted) { + if (onRetry) { + onRetry(res, () => { + this.isAborted = true; + }); + } + retry(res); + } + + throw res; + }); + }, + { + retries: FAULT_TOLERANT_HTTP_MAX_RETRIES, + maxTimeout: FAULT_TOLERANT_HTTP_MAX_RETRY_TIMEOUT + } + ); + } + }.retryHttp(); + }, // Server route defintions login(context, data) { @@ -126,10 +168,14 @@ export default { .get(`${API_ROOT}/volunteers`) .then(this._successHandler, this._errorHandler); }, - newSession(context, data) { - return context.$http - .post(`${API_ROOT}/session/new`, data) - .then(this._successHandler, this._errorHandler); + newSession(context, data, onRetry) { + return this._faultTolerantHttp( + context.$http, + "post", + onRetry, + `${API_ROOT}/session/new`, + data + ); }, endSession(context, data) { return context.$http From 905b8dc8f31fec91be1f6f2d65f1810f81354ce6 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 20:49:47 -0700 Subject: [PATCH 03/34] update package.json and package-lock.json --- package-lock.json | 21 +++++++++++++++++++++ package.json | 1 + 2 files changed, 22 insertions(+) diff --git a/package-lock.json b/package-lock.json index a8f5cff2..f5c467ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5041,6 +5041,11 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=" + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -12126,6 +12131,22 @@ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + } + } + }, "prompts": { "version": "0.1.14", "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz", diff --git a/package.json b/package.json index da07a41d..99567819 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "moment-timezone": "^0.5.26", "node-sass": "^4.13.1", "portal-gun": "git://github.com/claydotio/portal-gun.git", + "promise-retry": "^1.1.1", "sass-loader": "^7.1.0", "style-resources-loader": "^1.2.1", "typeface-work-sans": "0.0.72", From ba852757baba92479de9398505d4b8d27066de1d Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 20:50:07 -0700 Subject: [PATCH 04/34] fault tolerance in SessionService --- src/services/SessionService.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/services/SessionService.js b/src/services/SessionService.js index 4bc4e409..c900e7f9 100644 --- a/src/services/SessionService.js +++ b/src/services/SessionService.js @@ -26,11 +26,17 @@ export default { }); }, - newSession(context, sessionType, sessionSubTopic) { - return NetworkService.newSession(context, { - sessionType, - sessionSubTopic - }).then(res => { + newSession(context, sessionType, sessionSubTopic, options) { + const onRetry = options && options.onRetry; + + return NetworkService.newSession( + context, + { + sessionType, + sessionSubTopic + }, + onRetry + ).then(res => { const data = res.data || {}; const { sessionId } = data; From 3f93d3ebdd2dc53477b15f650d2f9391e1982a6d Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 20:51:56 -0700 Subject: [PATCH 05/34] monitor connection status in Vuex store --- src/views/SessionView/index.vue | 34 ++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/views/SessionView/index.vue b/src/views/SessionView/index.vue index 6ec971e8..614b38e4 100644 --- a/src/views/SessionView/index.vue +++ b/src/views/SessionView/index.vue @@ -89,14 +89,14 @@ export default { return { whiteboardOpen: false, icon: "Pencil.png", - sessionReconnecting: false, isNewSession: false }; }, computed: { ...mapState({ user: state => state.user.user, - session: state => state.user.session + session: state => state.user.session, + isSessionConnectionAlive: state => state.user.isSessionConnectionAlive }), ...mapGetters({ mobileMode: "app/mobileMode" @@ -143,12 +143,18 @@ export default { promise .then(sessionId => { + this.$store.dispatch("user/updateSession", { _id: sessionId }); this.$socket.io.opts.transports = ["polling", "websocket"]; - this.$socket.connect(); - this.joinSession(sessionId); + if (this.$socket.connected) { + this.joinSession(sessionId); + } else { + this.$socket.connect(); + } }) .catch(err => { - window.alert("Could not start new help session"); + if (err.status !== 0) { + window.alert("Could not start new help session"); + } this.$router.replace("/"); Sentry.captureException(err); }); @@ -168,16 +174,11 @@ export default { }); }, reconnect_attempt() { - this.sessionReconnecting = true; + this.$store.dispatch("user/sessionReconnectAttempt"); }, connect() { - if (this.sessionReconnecting) { - if (this.session && this.session._id) { - // we still need to re-join the room after Socket.IO re-establishes the connection - this.joinSession(this.session._id); - } else { - location.reload(); - } + if (!this.isSessionConnectionAlive) { + this.joinSession(this.session._id); } } }, @@ -213,6 +214,13 @@ export default { tryClicked() { this.sessionReconnecting = true; } + }, + watch: { + isSessionConnectionAlive(newValue, oldValue) { + if (newValue && !oldValue) { + this.$store.dispatch("app/modal/hide"); + } + } } }; From 179ae5f780d16eee020fa68498f842c976edcdf0 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 20:54:36 -0700 Subject: [PATCH 06/34] add new Vuex state for connection status --- src/store/modules/user.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/store/modules/user.js b/src/store/modules/user.js index cc780374..cd46857a 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -14,7 +14,8 @@ export default { session: {}, latestSession: {}, volunteerStats: {}, - isFirstDashboardVisit: false + isFirstDashboardVisit: false, + isSessionConnectionAlive: false }, mutations: { setUser: (state, user = {}) => (state.user = user), @@ -55,6 +56,10 @@ export default { setIsFirstDashboardVisit: (state, isFirstDashboardVisit) => { state.isFirstDashboardVisit = isFirstDashboardVisit; + }, + + setIsSessionConnectionAlive: (state, isSessionConnectionAlive) => { + state.isSessionConnectionAlive = isSessionConnectionAlive; } }, actions: { @@ -112,6 +117,14 @@ export default { commit("setSession", {}); }, + sessionReconnectAttempt: ({ commit }) => { + commit("setIsSessionConnectionAlive", false); + }, + + sessionConnected: ({ commit }) => { + commit("setIsSessionConnectionAlive", true); + }, + updateSession: ({ commit }, sessionData) => { commit("setSession", sessionData); }, From b3724f6aa5ddf19e844134ce8c298ac5bdc8c30c Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 20:55:23 -0700 Subject: [PATCH 07/34] update connection status when "session-change" is received --- src/components/App/index.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/App/index.vue b/src/components/App/index.vue index 68b8925c..72e26265 100644 --- a/src/components/App/index.vue +++ b/src/components/App/index.vue @@ -178,6 +178,7 @@ export default { SessionService.currentSession.data = sessionData; this.$store.dispatch("user/updateSession", sessionData); + this.$store.dispatch("user/sessionConnected"); } } }; From 533c34af5cffe0212ea6c4b4bb3a36333bdfa42d Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 20:55:55 -0700 Subject: [PATCH 08/34] modal dialog for when connection issues cause trouble starting a session --- .../SessionView/TroubleStartingModal.vue | 57 +++++++++++++++++++ src/views/SessionView/index.vue | 21 ++++++- 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/views/SessionView/TroubleStartingModal.vue diff --git a/src/views/SessionView/TroubleStartingModal.vue b/src/views/SessionView/TroubleStartingModal.vue new file mode 100644 index 00000000..58859882 --- /dev/null +++ b/src/views/SessionView/TroubleStartingModal.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/views/SessionView/index.vue b/src/views/SessionView/index.vue index 614b38e4..0be36e76 100644 --- a/src/views/SessionView/index.vue +++ b/src/views/SessionView/index.vue @@ -55,6 +55,7 @@ import Whiteboard from "./Whiteboard"; import SessionChat from "./SessionChat"; import SessionFulfilledModal from "./SessionFulfilledModal"; +import TroubleStartingModal from "./TroubleStartingModal"; const headerData = { component: "SessionHeader" @@ -133,7 +134,12 @@ export default { promise = SessionService.newSession( this, type, - this.$route.params.subTopic + this.$route.params.subTopic, + { + onRetry(res, abort) { + this.showTroubleStartingModal(abort); + } + } ); this.isNewSession = true; } else { @@ -175,6 +181,9 @@ export default { }, reconnect_attempt() { this.$store.dispatch("user/sessionReconnectAttempt"); + if (!this.session || !this.session._id) { + this.showTroubleStartingModal(); + } }, connect() { if (!this.isSessionConnectionAlive) { @@ -211,6 +220,16 @@ export default { user: this.user }); }, + showTroubleStartingModal(abort) { + this.$store.dispatch("app/modal/show", { + component: TroubleStartingModal, + data: { + acceptText: "Abort Session", + alertModal: true, + abortFunction: abort + } + }); + }, tryClicked() { this.sessionReconnecting = true; } From 0442b548981d78394862e737053a97b2b6243260 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 21:58:20 -0700 Subject: [PATCH 09/34] fix modal --- src/views/SessionView/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/SessionView/index.vue b/src/views/SessionView/index.vue index 0be36e76..b23fd639 100644 --- a/src/views/SessionView/index.vue +++ b/src/views/SessionView/index.vue @@ -136,7 +136,7 @@ export default { type, this.$route.params.subTopic, { - onRetry(res, abort) { + onRetry: (res, abort) => { this.showTroubleStartingModal(abort); } } From b6eef43a6d4ebce1134d6138173857df97b4c69b Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 21:59:00 -0700 Subject: [PATCH 10/34] generate new HTTP promise for each attempt --- src/services/NetworkService.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/services/NetworkService.js b/src/services/NetworkService.js index 536bee84..4c099d6c 100644 --- a/src/services/NetworkService.js +++ b/src/services/NetworkService.js @@ -18,21 +18,20 @@ export default { return Promise.reject(res); }, _faultTolerantHttp(http, method, onRetry, url, data) { - const promise = - ["get", "delete", "head", "jsonp"].indexOf(method) !== -1 - ? http[method](url, { timeout: FAULT_TOLERANT_HTTP_TIMEOUT }).then( - this._successHandler, - this._errorHandler - ) - : http[method](url, data, { - timeout: FAULT_TOLERANT_HTTP_TIMEOUT - }).then(this._successHandler, this._errorHandler); - return { isAborted: false, retryHttp: function() { return promiseRetry( retry => { + const promise = + ["get", "delete", "head", "jsonp"].indexOf(method) !== -1 + ? http[method](url, { + timeout: FAULT_TOLERANT_HTTP_TIMEOUT + }).then(this._successHandler, this._errorHandler) + : http[method](url, data, { + timeout: FAULT_TOLERANT_HTTP_TIMEOUT + }).then(this._successHandler, this._errorHandler); + return promise.catch(res => { if (res.status === 0 && !this.isAborted) { if (onRetry) { From 8ead1e1e2a975cfa98f058529a7128407f3f4f47 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 21:59:15 -0700 Subject: [PATCH 11/34] increase max timeout --- src/services/NetworkService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/NetworkService.js b/src/services/NetworkService.js index 4c099d6c..07ba339f 100644 --- a/src/services/NetworkService.js +++ b/src/services/NetworkService.js @@ -7,7 +7,7 @@ const ELIGIBILITY_API_ROOT = `${process.env.VUE_APP_SERVER_ROOT}/eligibility`; const CONTACT_API_ROOT = `${process.env.VUE_APP_SERVER_ROOT}/contact`; const FAULT_TOLERANT_HTTP_TIMEOUT = 10000; -const FAULT_TOLERANT_HTTP_MAX_RETRY_TIMEOUT = 10000; +const FAULT_TOLERANT_HTTP_MAX_RETRY_TIMEOUT = 100000; const FAULT_TOLERANT_HTTP_MAX_RETRIES = 10; export default { From d7e34f4ce1340926a9c7cb25891c15396380e3d9 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 22:17:44 -0700 Subject: [PATCH 12/34] don't retry after user aborts --- src/services/NetworkService.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/services/NetworkService.js b/src/services/NetworkService.js index 07ba339f..13ae3268 100644 --- a/src/services/NetworkService.js +++ b/src/services/NetworkService.js @@ -1,5 +1,6 @@ import Vue from "vue"; import promiseRetry from "promise-retry"; +import errcode from "err-code"; const AUTH_ROOT = `${process.env.VUE_APP_SERVER_ROOT}/auth`; const API_ROOT = `${process.env.VUE_APP_SERVER_ROOT}/api`; @@ -23,6 +24,13 @@ export default { retryHttp: function() { return promiseRetry( retry => { + if (this.isAborted) { + // early exit + return Promise.reject( + errcode(new Error("Aborted by user"), "EUSERABORTED") + ); + } + const promise = ["get", "delete", "head", "jsonp"].indexOf(method) !== -1 ? http[method](url, { @@ -33,7 +41,7 @@ export default { }).then(this._successHandler, this._errorHandler); return promise.catch(res => { - if (res.status === 0 && !this.isAborted) { + if (res.status === 0) { if (onRetry) { onRetry(res, () => { this.isAborted = true; From 4853bf62b433f9b5b2b77694405e290b20c17a73 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Fri, 8 May 2020 22:18:02 -0700 Subject: [PATCH 13/34] don't show error message when user aborts --- src/views/SessionView/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/SessionView/index.vue b/src/views/SessionView/index.vue index b23fd639..3df0336b 100644 --- a/src/views/SessionView/index.vue +++ b/src/views/SessionView/index.vue @@ -158,7 +158,7 @@ export default { } }) .catch(err => { - if (err.status !== 0) { + if (err.status !== 0 && err.code !== "EUSERABORTED") { window.alert("Could not start new help session"); } this.$router.replace("/"); From fec7a70bcd8c5cc17ee483742238163cd3ed73d7 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Sat, 9 May 2020 10:57:32 -0700 Subject: [PATCH 14/34] track when session is disconnected by user --- src/store/modules/user.js | 2 +- src/views/SessionView/SessionHeader.vue | 2 ++ src/views/SessionView/index.vue | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/store/modules/user.js b/src/store/modules/user.js index cd46857a..d43786a9 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -117,7 +117,7 @@ export default { commit("setSession", {}); }, - sessionReconnectAttempt: ({ commit }) => { + sessionDisconnected: ({ commit }) => { commit("setIsSessionConnectionAlive", false); }, diff --git a/src/views/SessionView/SessionHeader.vue b/src/views/SessionView/SessionHeader.vue index efe3f3f0..e8f87d58 100644 --- a/src/views/SessionView/SessionHeader.vue +++ b/src/views/SessionView/SessionHeader.vue @@ -167,6 +167,7 @@ export default { SessionService.endSession(this, sessionId) .then(() => { this.$socket.disconnect(); + this.$store.dispatch("user/sessionDisconnected"); const url = "/feedback/" + sessionId + @@ -187,6 +188,7 @@ export default { SessionService.endSession(this, sessionId) .then(() => { this.$socket.disconnect(); + this.$store.dispatch("user/sessionDisconnected"); router.push("/"); }) .catch(this.alertCouldNotEnd); diff --git a/src/views/SessionView/index.vue b/src/views/SessionView/index.vue index 3df0336b..8b95480c 100644 --- a/src/views/SessionView/index.vue +++ b/src/views/SessionView/index.vue @@ -180,7 +180,7 @@ export default { }); }, reconnect_attempt() { - this.$store.dispatch("user/sessionReconnectAttempt"); + this.$store.dispatch("user/sessionDisconnected"); if (!this.session || !this.session._id) { this.showTroubleStartingModal(); } From 467908c828014008fcd79371bd83c415e192992b Mon Sep 17 00:00:00 2001 From: David Nisson Date: Sat, 9 May 2020 10:57:48 -0700 Subject: [PATCH 15/34] display connection warning message in chat --- src/views/SessionView/SessionChat/index.vue | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/views/SessionView/SessionChat/index.vue b/src/views/SessionView/SessionChat/index.vue index 27e8efb8..9f3d5cc9 100644 --- a/src/views/SessionView/SessionChat/index.vue +++ b/src/views/SessionView/SessionChat/index.vue @@ -17,6 +17,11 @@ > + +
+ Please check your Internet connection +
+
@@ -100,12 +105,17 @@ export default { message.avatarStyle = { backgroundImage: `url(${picture})` }; return message; - }) + }), + isSessionConnectionAlive: state => state.user.isSessionConnectionAlive, }), ...mapGetters({ sessionPartner: "user/sessionPartner", - isSessionWaitingForVolunteer: "user/isSessionWaitingForVolunteer" - }) + isSessionWaitingForVolunteer: "user/isSessionWaitingForVolunteer", + isSessionOver: "user/isSessionOver" + }), + connectionWarningIsShown: function() { + return !this.isSessionConnectionAlive && this.isSessionAlive; + } }, methods: { showModerationWarning() { From bed6ba39b7d9dde3a8fe299a72555683c33402a4 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Sat, 9 May 2020 10:59:31 -0700 Subject: [PATCH 16/34] lint --- src/views/SessionView/SessionChat/index.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/SessionView/SessionChat/index.vue b/src/views/SessionView/SessionChat/index.vue index 9f3d5cc9..17877422 100644 --- a/src/views/SessionView/SessionChat/index.vue +++ b/src/views/SessionView/SessionChat/index.vue @@ -19,7 +19,7 @@
- Please check your Internet connection + Please check your Internet connection
@@ -106,7 +106,7 @@ export default { message.avatarStyle = { backgroundImage: `url(${picture})` }; return message; }), - isSessionConnectionAlive: state => state.user.isSessionConnectionAlive, + isSessionConnectionAlive: state => state.user.isSessionConnectionAlive }), ...mapGetters({ sessionPartner: "user/sessionPartner", From b14646695788a0e54b18f368429c4af9d9dab785 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Sat, 9 May 2020 11:12:34 -0700 Subject: [PATCH 17/34] fix computed prop --- src/views/SessionView/SessionChat/index.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/SessionView/SessionChat/index.vue b/src/views/SessionView/SessionChat/index.vue index 17877422..32884a78 100644 --- a/src/views/SessionView/SessionChat/index.vue +++ b/src/views/SessionView/SessionChat/index.vue @@ -18,7 +18,7 @@
-
+
Please check your Internet connection
@@ -111,9 +111,9 @@ export default { ...mapGetters({ sessionPartner: "user/sessionPartner", isSessionWaitingForVolunteer: "user/isSessionWaitingForVolunteer", - isSessionOver: "user/isSessionOver" + isSessionAlive: "user/isSessionAlive" }), - connectionWarningIsShown: function() { + isSessionConnectionFailure: function() { return !this.isSessionConnectionAlive && this.isSessionAlive; } }, From d36e72fb4784b1927aed6f60243dd30d0b44e2f5 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Mon, 11 May 2020 21:10:17 -0700 Subject: [PATCH 18/34] update to reflect server changes * no longer need to join session every time we reconnect --- src/components/App/index.vue | 1 - src/views/SessionView/index.vue | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/App/index.vue b/src/components/App/index.vue index 72e26265..68b8925c 100644 --- a/src/components/App/index.vue +++ b/src/components/App/index.vue @@ -178,7 +178,6 @@ export default { SessionService.currentSession.data = sessionData; this.$store.dispatch("user/updateSession", sessionData); - this.$store.dispatch("user/sessionConnected"); } } }; diff --git a/src/views/SessionView/index.vue b/src/views/SessionView/index.vue index 8b95480c..f2bd9a2a 100644 --- a/src/views/SessionView/index.vue +++ b/src/views/SessionView/index.vue @@ -186,7 +186,15 @@ export default { } }, connect() { - if (!this.isSessionConnectionAlive) { + this.$store.dispatch("user/sessionConnected"); + + if (!this.session || !this.session._id + || ( + (!this.session.student || this.session.student._id !== this.user._id) && + (!this.session.volunteer || this.session.volunteer._id !== this.user._id) + ) + ) { + // join the session if we haven't done so already this.joinSession(this.session._id); } } From ecdff8fa6db6268774435f04a392504b93a9c4e6 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Mon, 11 May 2020 22:00:48 -0700 Subject: [PATCH 19/34] join session using id from route --- src/views/SessionView/index.vue | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/views/SessionView/index.vue b/src/views/SessionView/index.vue index f2bd9a2a..93a3260a 100644 --- a/src/views/SessionView/index.vue +++ b/src/views/SessionView/index.vue @@ -149,7 +149,6 @@ export default { promise .then(sessionId => { - this.$store.dispatch("user/updateSession", { _id: sessionId }); this.$socket.io.opts.transports = ["polling", "websocket"]; if (this.$socket.connected) { this.joinSession(sessionId); @@ -188,14 +187,16 @@ export default { connect() { this.$store.dispatch("user/sessionConnected"); - if (!this.session || !this.session._id - || ( + if (this.session && this.session._id) { + if ( (!this.session.student || this.session.student._id !== this.user._id) && (!this.session.volunteer || this.session.volunteer._id !== this.user._id) - ) - ) { - // join the session if we haven't done so already - this.joinSession(this.session._id); + ) { + // join the session if we haven't done so already + this.joinSession(this.session._id); + } + } else if (this.$route.params.sessionId) { + this.joinSession(this.$route.params.sessionId); } } }, From 93b0f44fb128da3f0b3af2c2838bd0b9945c9a67 Mon Sep 17 00:00:00 2001 From: David Nisson Date: Tue, 12 May 2020 13:03:45 -0700 Subject: [PATCH 20/34] improve readability of faultTolerantHttp function --- src/services/NetworkService.js | 71 +++++++++++++++++----------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/src/services/NetworkService.js b/src/services/NetworkService.js index 13ae3268..db3ecffb 100644 --- a/src/services/NetworkService.js +++ b/src/services/NetworkService.js @@ -19,47 +19,46 @@ export default { return Promise.reject(res); }, _faultTolerantHttp(http, method, onRetry, url, data) { - return { - isAborted: false, - retryHttp: function() { - return promiseRetry( - retry => { - if (this.isAborted) { - // early exit - return Promise.reject( - errcode(new Error("Aborted by user"), "EUSERABORTED") - ); - } + const promiseToRetry = () => { + return ( + ["get", "delete", "head", "jsonp"].indexOf(method) !== -1 + ? http[method](url, { + timeout: FAULT_TOLERANT_HTTP_TIMEOUT + }) + : http[method](url, data, { + timeout: FAULT_TOLERANT_HTTP_TIMEOUT + }) + ).then(this._successHandler, this._errorHandler); + }; - const promise = - ["get", "delete", "head", "jsonp"].indexOf(method) !== -1 - ? http[method](url, { - timeout: FAULT_TOLERANT_HTTP_TIMEOUT - }).then(this._successHandler, this._errorHandler) - : http[method](url, data, { - timeout: FAULT_TOLERANT_HTTP_TIMEOUT - }).then(this._successHandler, this._errorHandler); + // object property specifying whether this function is aborted + const requestState = { isAborted: false } - return promise.catch(res => { - if (res.status === 0) { - if (onRetry) { - onRetry(res, () => { - this.isAborted = true; - }); - } - retry(res); - } + return promiseRetry( + retry => { + if (requestState.isAborted) { + // early exit + throw errcode(new Error("Aborted by user"), "EUSERABORTED"); + } - throw res; - }); - }, - { - retries: FAULT_TOLERANT_HTTP_MAX_RETRIES, - maxTimeout: FAULT_TOLERANT_HTTP_MAX_RETRY_TIMEOUT + return promiseToRetry().catch(res => { + if (res.status === 0) { + if (onRetry) { + onRetry(res, () => { + requestState.isAborted = true; + }); + } + retry(res); } - ); + + throw res; + }); + }, + { + retries: FAULT_TOLERANT_HTTP_MAX_RETRIES, + maxTimeout: FAULT_TOLERANT_HTTP_MAX_RETRY_TIMEOUT } - }.retryHttp(); + ); }, // Server route defintions From 828f2071f43c5f4a06305c03547736ee4ae4ad5d Mon Sep 17 00:00:00 2001 From: David Nisson Date: Tue, 12 May 2020 14:57:03 -0700 Subject: [PATCH 21/34] turn TroubleStartingModal into a generic ConnectionTroubleModal --- ...artingModal.vue => ConnectionTroubleModal.vue} | 15 +++++++-------- src/views/SessionView/index.vue | 13 +++++++++++-- 2 files changed, 18 insertions(+), 10 deletions(-) rename src/views/SessionView/{TroubleStartingModal.vue => ConnectionTroubleModal.vue} (72%) diff --git a/src/views/SessionView/TroubleStartingModal.vue b/src/views/SessionView/ConnectionTroubleModal.vue similarity index 72% rename from src/views/SessionView/TroubleStartingModal.vue rename to src/views/SessionView/ConnectionTroubleModal.vue index 58859882..a0a1fce2 100644 --- a/src/views/SessionView/TroubleStartingModal.vue +++ b/src/views/SessionView/ConnectionTroubleModal.vue @@ -1,9 +1,8 @@