MM-11477 Ensure client calls are wrapped with error handling (#1976)

This commit is contained in:
Harrison Healey 2018-08-07 13:11:48 -04:00 committed by Elias Nahum
parent 979b80d34f
commit 34a37cef05
7 changed files with 56 additions and 21 deletions

View file

@ -6,7 +6,7 @@ import {GeneralTypes} from 'mattermost-redux/action_types';
import {autoUpdateTimezone} from 'mattermost-redux/actions/timezone';
import {Client4} from 'mattermost-redux/client';
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import {getCurrentUserId, getSessions} from 'mattermost-redux/selectors/entities/users';
import {ViewTypes} from 'app/constants';
import {app} from 'app/mattermost';
@ -73,15 +73,25 @@ export function getSession() {
const {credentials} = state.entities.general;
const token = credentials && credentials.token;
if (currentUserId && token) {
const session = await Client4.getSessions(currentUserId, token);
if (Array.isArray(session) && session[0]) {
const s = session[0];
return s.expires_at;
}
if (!currentUserId || !token) {
return 0;
}
return false;
let sessions;
try {
sessions = await getSessions(currentUserId);
} catch (e) {
console.warn('Failed to get current session', e); // eslint-disable-line no-console
return 0;
}
if (!Array.isArray(sessions)) {
return 0;
}
const session = sessions.find((s) => s.token === token);
return session && session.expires_at ? session.expires_at : 0;
};
}

View file

@ -102,7 +102,9 @@ export function purgeOfflineStore() {
return {type: General.OFFLINE_STORE_PURGE};
}
export function createPost(post) {
// A non-optimistic version of the createPost action in mattermost-redux with the file handling
// removed since it's not needed.
export function createPostForNotificationReply(post) {
return (dispatch, getState) => {
const state = getState();
const currentUserId = state.entities.users.currentUserId;

View file

@ -259,7 +259,13 @@ export default class App {
if (this.token && this.url) {
screen = 'Channel';
tracker.initialLoad = Date.now();
dispatch(loadMe());
try {
dispatch(loadMe());
} catch (e) {
// Fall through since we should have a previous version of the current user because we have a token
console.warn('Failed to load current user when starting on Channel screen', e); // eslint-disable-line no-console
}
}
switch (screen) {

View file

@ -42,6 +42,7 @@ Client4.doFetchWithResponse = async (url, options) => {
}
throw {
message: 'Received invalid response from the server.',
intl: {
id: 'mobile.request.invalid_response',
defaultMessage: 'Received invalid response from the server.',

View file

@ -142,8 +142,13 @@ const handleLogout = () => {
const restartApp = async () => {
Navigation.dismissModal({animationType: 'none'});
await store.dispatch(loadConfigAndLicense());
await store.dispatch(loadMe());
try {
await store.dispatch(loadConfigAndLicense());
await store.dispatch(loadMe());
} catch (e) {
console.warn('Failed to load initial data while restarting', e); // eslint-disable-line no-console
}
launchChannel();
};

View file

@ -187,12 +187,18 @@ class SSO extends PureComponent {
setStoreFromLocalData({url: this.props.serverUrl, token}).
then(handleSuccessfulLogin).
then(getSession).
then(this.goToLoadTeam);
then(this.goToLoadTeam).
catch(this.onLoadEndError);
}
});
}
};
onLoadEndError = (e) => {
console.warn('Failed to set store from local data', e); // eslint-disable-line no-console
this.setState({error: e.message});
}
renderLoading = () => {
return <Loading/>;
};

View file

@ -16,7 +16,7 @@ import EventEmitter from 'mattermost-redux/utils/event_emitter';
import {ViewTypes} from 'app/constants';
import {retryGetPostsAction} from 'app/actions/views/channel';
import {
createPost,
createPostForNotificationReply,
loadFromPushNotification,
} from 'app/actions/views/root';
@ -136,15 +136,20 @@ export const onPushNotificationReply = (data, text, badge, completed) => {
}
retryGetPostsAction(getPosts(data.channel_id), dispatch, getState);
dispatch(createPost(post)).then(() => {
dispatch(markChannelAsRead(data.channel_id));
dispatch(createPostForNotificationReply(post)).
then(() => {
dispatch(markChannelAsRead(data.channel_id));
if (badge >= 0) {
PushNotifications.setApplicationIconBadgeNumber(badge);
}
if (badge >= 0) {
PushNotifications.setApplicationIconBadgeNumber(badge);
}
app.setReplyNotificationData(null);
}).then(completed);
app.setReplyNotificationData(null);
}).
then(completed).
catch((e) => {
console.warn('Failed to send reply to push notification', e); // eslint-disable-line no-console
});
} else {
app.setReplyNotificationData({
data,