Browse Source

[RN] Fix processing outdated loadConfig requests (continued)

Co-authored-by: Lyubo Marinov <lmarinov@atlassian.com>
Co-authored-by: Paweł Domas <pawel.domas@jitsi.org>
master
Lyubo Marinov 7 years ago
parent
commit
592305df74

+ 29
- 25
react/features/app/actions.js View File

1
-/* @flow */
1
+// @flow
2
 
2
 
3
 import type { Dispatch } from 'redux';
3
 import type { Dispatch } from 'redux';
4
 
4
 
51
         newLocation: Object
51
         newLocation: Object
52
 ): Promise<void> {
52
 ): Promise<void> {
53
     const { room } = newLocation;
53
     const { room } = newLocation;
54
+    const locationURL = new URL(newLocation.toString());
54
 
55
 
55
-    dispatch(configWillLoad(newLocation));
56
+    dispatch(configWillLoad(locationURL));
56
 
57
 
57
     return (
58
     return (
58
         _loadConfig(dispatch, getState, newLocation)
59
         _loadConfig(dispatch, getState, newLocation)
73
      * @returns {void}
74
      * @returns {void}
74
      */
75
      */
75
     function loadConfigSettled(error, config) {
76
     function loadConfigSettled(error, config) {
76
-        // Due to the asynchronous nature of the loading, the specified
77
-        // config may or may not be required by the time the notification
78
-        // arrives. If we receive the config for a location we are no longer
79
-        // interested in, just dump it.
80
-
81
-        const { locationURL: currentLocationURL }
82
-            = getState()['features/base/config'];
83
-
84
-        if (currentLocationURL !== newLocation) {
85
-            throw new Error('Config no longer needed');
77
+        let promise;
78
+
79
+        // Due to the asynchronous nature of the loading, the specified config
80
+        // may or may not be required by the time the notification arrives.
81
+        // If we receive the config for a location we are no longer interested
82
+        // in, "ignore" it - deliver it to the external API, for example, but do
83
+        // not proceed with the appNavigate procedure/process.
84
+        if (getState()['features/base/config'].locationURL === locationURL) {
85
+            promise = dispatch(setLocationURL(locationURL));
86
+        } else {
87
+            // eslint-disable-next-line no-param-reassign
88
+            error || (error = new Error('Config no longer needed!'));
89
+            promise = Promise.resolve();
86
         }
90
         }
87
 
91
 
88
-        const promise
89
-            = dispatch(setLocationURL(new URL(newLocation.toString())));
90
-
91
-        if (error) {
92
-            // XXX The failure could be, for example, because of a
93
-            // certificate-related error. In which case the connection will
94
-            // fail later in Strophe anyway.
95
-            return promise.then(() => {
96
-                dispatch(loadConfigError(error, newLocation));
92
+        return promise.then(() => {
93
+            if (error) {
94
+                // XXX The failure could be, for example, because of a
95
+                // certificate-related error. In which case the connection will
96
+                // fail later in Strophe anyway.
97
+                dispatch(loadConfigError(error, locationURL));
97
                 throw error;
98
                 throw error;
98
-            });
99
-        }
99
+            }
100
 
100
 
101
-        return promise.then(() =>
102
-            dispatch(setConfig(config)));
101
+            return dispatch(setConfig(config));
102
+        });
103
     }
103
     }
104
 }
104
 }
105
 
105
 
227
 
227
 
228
     return loadConfig(url).then(
228
     return loadConfig(url).then(
229
         /* onFulfilled */ config => {
229
         /* onFulfilled */ config => {
230
+            // FIXME If the config is no longer needed (in the terms of
231
+            // _loadConfig) and that happened because of an intervening
232
+            // _loadConfig for the same baseURL, then the unneeded config may be
233
+            // stored after the needed config. Anyway.
230
             dispatch(storeConfig(baseURL, config));
234
             dispatch(storeConfig(baseURL, config));
231
 
235
 
232
             return config;
236
             return config;

+ 6
- 6
react/features/base/config/actionTypes.js View File

1
 /**
1
 /**
2
- * The redux action which signals that a configuration will be loaded for a
3
- * specific locationURL.
2
+ * The redux action which signals that a configuration (commonly known in Jitsi
3
+ * Meet as config.js) will be loaded for a specific locationURL.
4
  *
4
  *
5
  * {
5
  * {
6
  *     type: CONFIG_WILL_LOAD,
6
  *     type: CONFIG_WILL_LOAD,
7
- *     locationURL: string | URL
7
+ *     locationURL: URL
8
  * }
8
  * }
9
  */
9
  */
10
 export const CONFIG_WILL_LOAD = Symbol('CONFIG_WILL_LOAD');
10
 export const CONFIG_WILL_LOAD = Symbol('CONFIG_WILL_LOAD');
11
 
11
 
12
 /**
12
 /**
13
- * The redux action which signals that a configuration could not be loaded due
14
- * to a specific error.
13
+ * The redux action which signals that a configuration (commonly known in Jitsi
14
+ * Meet as config.js) could not be loaded due to a specific error.
15
  *
15
  *
16
  * {
16
  * {
17
  *     type: LOAD_CONFIG_ERROR,
17
  *     type: LOAD_CONFIG_ERROR,
18
  *     error: Error,
18
  *     error: Error,
19
- *     locationURL: string | URL
19
+ *     locationURL: URL
20
  * }
20
  * }
21
  */
21
  */
22
 export const LOAD_CONFIG_ERROR = Symbol('LOAD_CONFIG_ERROR');
22
 export const LOAD_CONFIG_ERROR = Symbol('LOAD_CONFIG_ERROR');

+ 13
- 15
react/features/base/config/actions.js View File

5
 import { addKnownDomains } from '../known-domains';
5
 import { addKnownDomains } from '../known-domains';
6
 import { parseURIString } from '../util';
6
 import { parseURIString } from '../util';
7
 
7
 
8
-import {
9
-    CONFIG_WILL_LOAD,
10
-    LOAD_CONFIG_ERROR,
11
-    SET_CONFIG
12
-} from './actionTypes';
8
+import { CONFIG_WILL_LOAD, LOAD_CONFIG_ERROR, SET_CONFIG } from './actionTypes';
13
 import { _CONFIG_STORE_PREFIX } from './constants';
9
 import { _CONFIG_STORE_PREFIX } from './constants';
14
 import { setConfigFromURLParams } from './functions';
10
 import { setConfigFromURLParams } from './functions';
15
 
11
 
16
 /**
12
 /**
17
- * Signals that the configuration for a specific locationURL will be loaded now.
13
+ * Signals that the configuration (commonly known in Jitsi Meet as config.js)
14
+ * for a specific locationURL will be loaded now.
18
  *
15
  *
19
- * @param {string|URL} locationURL - The URL of the location which necessitated
20
- * the loading of a configuration.
16
+ * @param {URL} locationURL - The URL of the location which necessitated the
17
+ * loading of a configuration.
21
  * @returns {{
18
  * @returns {{
22
  *     type: CONFIG_WILL_LOAD,
19
  *     type: CONFIG_WILL_LOAD,
23
- *     locationURL
20
+ *     locationURL: URL
24
  * }}
21
  * }}
25
  */
22
  */
26
-export function configWillLoad(locationURL: string | URL) {
23
+export function configWillLoad(locationURL: URL) {
27
     return {
24
     return {
28
         type: CONFIG_WILL_LOAD,
25
         type: CONFIG_WILL_LOAD,
29
         locationURL
26
         locationURL
31
 }
28
 }
32
 
29
 
33
 /**
30
 /**
34
- * Signals that a configuration could not be loaded due to a specific error.
31
+ * Signals that a configuration (commonly known in Jitsi Meet as config.js)
32
+ * could not be loaded due to a specific error.
35
  *
33
  *
36
  * @param {Error} error - The {@code Error} which prevented the successful
34
  * @param {Error} error - The {@code Error} which prevented the successful
37
  * loading of a configuration.
35
  * loading of a configuration.
38
- * @param {string|URL} locationURL - The URL of the location which necessitated
39
- * the loading of a configuration.
36
+ * @param {URL} locationURL - The URL of the location which necessitated the
37
+ * loading of a configuration.
40
  * @returns {{
38
  * @returns {{
41
  *     type: LOAD_CONFIG_ERROR,
39
  *     type: LOAD_CONFIG_ERROR,
42
  *     error: Error,
40
  *     error: Error,
43
- *     locationURL
41
+ *     locationURL: URL
44
  * }}
42
  * }}
45
  */
43
  */
46
-export function loadConfigError(error: Error, locationURL: string | URL) {
44
+export function loadConfigError(error: Error, locationURL: URL) {
47
     return {
45
     return {
48
         type: LOAD_CONFIG_ERROR,
46
         type: LOAD_CONFIG_ERROR,
49
         error,
47
         error,

+ 29
- 12
react/features/base/config/reducer.js View File

1
-/* @flow */
1
+// @flow
2
 
2
 
3
 import _ from 'lodash';
3
 import _ from 'lodash';
4
 
4
 
5
 import { equals, ReducerRegistry, set } from '../redux';
5
 import { equals, ReducerRegistry, set } from '../redux';
6
 
6
 
7
-import {
8
-    CONFIG_WILL_LOAD,
9
-    LOAD_CONFIG_ERROR,
10
-    SET_CONFIG
11
-} from './actionTypes';
7
+import { CONFIG_WILL_LOAD, LOAD_CONFIG_ERROR, SET_CONFIG } from './actionTypes';
12
 
8
 
13
 /**
9
 /**
14
  * The initial state of the feature base/config when executing in a
10
  * The initial state of the feature base/config when executing in a
54
         case CONFIG_WILL_LOAD:
50
         case CONFIG_WILL_LOAD:
55
             return {
51
             return {
56
                 error: undefined,
52
                 error: undefined,
53
+
54
+                /**
55
+                 * The URL of the location associated with/configured by this
56
+                 * configuration.
57
+                 *
58
+                 * @type URL
59
+                 */
57
                 locationURL: action.locationURL
60
                 locationURL: action.locationURL
58
             };
61
             };
59
 
62
 
60
         case LOAD_CONFIG_ERROR:
63
         case LOAD_CONFIG_ERROR:
61
-            return {
62
-                error: action.error
63
-            };
64
+            // XXX LOAD_CONFIG_ERROR is one of the settlement execution paths of
65
+            // the asynchronous "loadConfig procedure/process" started with
66
+            // CONFIG_WILL_LOAD. Due to the asynchronous nature of it, whoever
67
+            // is settling the process needs to provide proof that they have
68
+            // started it and that the iteration of the process being completed
69
+            // now is still of interest to the app.
70
+            if (state.locationURL === action.locationURL) {
71
+                return {
72
+                    /**
73
+                     * The {@link Error} which prevented the loading of the
74
+                     * configuration of the associated {@code locationURL}.
75
+                     *
76
+                     * @type Error
77
+                     */
78
+                    error: action.error
79
+                };
80
+            }
81
+            break;
64
 
82
 
65
         case SET_CONFIG:
83
         case SET_CONFIG:
66
             return _setConfig(state, action);
84
             return _setConfig(state, action);
67
-
68
-        default:
69
-            return state;
70
         }
85
         }
86
+
87
+        return state;
71
     });
88
     });
72
 
89
 
73
 /**
90
 /**

+ 11
- 7
react/features/mobile/external-api/middleware.js View File

28
  */
28
  */
29
 MiddlewareRegistry.register(store => next => action => {
29
 MiddlewareRegistry.register(store => next => action => {
30
     const result = next(action);
30
     const result = next(action);
31
+    const { type } = action;
31
 
32
 
32
-    switch (action.type) {
33
+    switch (type) {
33
     case CONFERENCE_FAILED: {
34
     case CONFERENCE_FAILED: {
34
         const { error, ...data } = action;
35
         const { error, ...data } = action;
35
 
36
 
64
         break;
65
         break;
65
 
66
 
66
     case ENTER_PICTURE_IN_PICTURE:
67
     case ENTER_PICTURE_IN_PICTURE:
67
-        _sendEvent(store, _getSymbolDescription(action.type), /* data */ {});
68
+        _sendEvent(store, _getSymbolDescription(type), /* data */ {});
68
         break;
69
         break;
69
 
70
 
70
     case LOAD_CONFIG_ERROR: {
71
     case LOAD_CONFIG_ERROR: {
71
-        const { error, locationURL, type } = action;
72
+        const { error, locationURL } = action;
72
 
73
 
73
-        _sendEvent(store, _getSymbolDescription(type), /* data */ {
74
-            error: _toErrorString(error),
75
-            url: toURLString(locationURL)
76
-        });
74
+        _sendEvent(
75
+            store,
76
+            _getSymbolDescription(type),
77
+            /* data */ {
78
+                error: _toErrorString(error),
79
+                url: toURLString(locationURL)
80
+            });
77
         break;
81
         break;
78
     }
82
     }
79
 
83
 

Loading…
Cancel
Save