Browse Source

feat(XmppConnection): use full jitter backoff patter for resume retry

dev1
paweldomas 5 years ago
parent
commit
8a41d02407
2 changed files with 35 additions and 2 deletions
  1. 14
    0
      modules/util/Retry.js
  2. 21
    2
      modules/xmpp/XmppConnection.js

+ 14
- 0
modules/util/Retry.js View File

@@ -0,0 +1,14 @@
1
+/**
2
+* Gets next timeout using the full jitter pattern.
3
+*
4
+* NOTE that there are no checks for argument correctness, so either do the math or use defaults.
5
+*
6
+* @param {number} retry - The retry number.
7
+* @param {number} minDelay - The minimal delay in milliseconds.
8
+* @param {number} base - The exponent base.
9
+* @returns {number} - The amount of waiting before trying another time given in milliseconds.
10
+* @private
11
+*/
12
+export function getJitterDelay(retry, minDelay = 500, base = 2) {
13
+    return Math.floor((Math.random() * ((Math.pow(base, retry) * 1000) - minDelay)) + minDelay);
14
+}

+ 21
- 2
modules/xmpp/XmppConnection.js View File

@@ -3,6 +3,7 @@ import { $pres, Strophe } from 'strophe.js';
3 3
 import 'strophejs-plugin-stream-management';
4 4
 
5 5
 import Listenable from '../util/Listenable';
6
+import { getJitterDelay } from '../util/Retry';
6 7
 
7 8
 import LastSuccessTracker from './StropheBoshLastSuccess';
8 9
 
@@ -50,6 +51,13 @@ export default class XmppConnection extends Listenable {
50 51
             enableWebsocketResume: typeof enableWebsocketResume === 'undefined' ? true : enableWebsocketResume,
51 52
             websocketKeepAlive: typeof websocketKeepAlive === 'undefined' ? 4 * 60 * 1000 : Number(websocketKeepAlive)
52 53
         };
54
+
55
+        /**
56
+         * The counter increased before each resume retry attempt, used to calculate exponential backoff.
57
+         * @type {number}
58
+         * @private
59
+         */
60
+        this._resumeRetryN = 0;
53 61
         this._stropheConn = new Strophe.Connection(serviceUrl);
54 62
         this._usesWebsocket = serviceUrl.startsWith('ws:') || serviceUrl.startsWith('wss:');
55 63
 
@@ -206,6 +214,7 @@ export default class XmppConnection extends Listenable {
206 214
             if (status === Strophe.Status.CONNECTED) {
207 215
                 this._maybeEnableStreamResume();
208 216
                 this._maybeStartWSKeepAlive();
217
+                this._resumeRetryN = 0;
209 218
             } else if (status === Strophe.Status.DISCONNECTED) {
210 219
                 // FIXME add RECONNECTING state instead of blocking the DISCONNECTED update
211 220
                 blockCallback = this._tryResumingConnection();
@@ -421,6 +430,17 @@ export default class XmppConnection extends Listenable {
421 430
 
422 431
         if (resumeToken) {
423 432
             clearTimeout(this._resumeTimeout);
433
+
434
+            // FIXME detect internet offline
435
+            // The retry delay will be:
436
+            //   1st retry: 1.5s - 3s
437
+            //   2nd retry: 3s - 9s
438
+            //   3rd retry: 3s - 27s
439
+            this._resumeRetryN = Math.min(3, this._resumeRetryN + 1);
440
+            const retryTimeout = getJitterDelay(this._resumeRetryN, 1500, 3);
441
+
442
+            logger.info(`Will try to resume the XMPP connection in ${retryTimeout}ms`);
443
+
424 444
             this._resumeTimeout = setTimeout(() => {
425 445
                 logger.info('Trying to resume the XMPP connection');
426 446
 
@@ -428,11 +448,10 @@ export default class XmppConnection extends Listenable {
428 448
 
429 449
                 url.searchParams.set('previd', resumeToken);
430 450
 
431
-                // FIXME remove XmppConnection 'service' setter
432 451
                 this._stropheConn.service = url.toString();
433 452
 
434 453
                 streamManagement.resume();
435
-            }, 3000 /* FIXME calculate delay with jitter */);
454
+            }, retryTimeout);
436 455
 
437 456
             return true;
438 457
         }

Loading…
Cancel
Save