Merge branch 'docs-header-fix' into 'main'
[ProtonMail-WebClient.git] / packages / docs-core / lib / Realtime / WebsocketState.ts
blobaa77901267743ba17481a59fdb73c068818fc436
1 const MinimumJitterFactor = 1
2 const MaximumJitterFactor = 1.5
3 const MaxBackoffInMilliseconds = 32_000
5 /**
6  * If the connection is still connected after this time, reset backoff attempts. This is to avoid cases where a conneciton open then quickly shutters, which would bypass increasing exponentinal backoff. Instead, we wait this interval before deciding to reset connection attempts
7  */
8 const BackoffResetThresholdInMilliseconds = 10_000
10 export interface WebsocketStateInterface {
11   didOpen(): void
12   didFailToFetchToken(): void
13   didClose(): void
14   isConnected: boolean
15   getBackoff(): number
16   destroy(): void
19 export class WebsocketState implements WebsocketStateInterface {
20   private attempts = 0
21   private connected: boolean = false
22   private resetTimeout: ReturnType<typeof setTimeout> | null = null
24   didOpen() {
25     this.connected = true
27     if (this.resetTimeout) {
28       clearTimeout(this.resetTimeout)
29     }
31     this.resetTimeout = setTimeout(() => {
32       if (this.connected) {
33         this.resetAttempts()
34       }
35     }, BackoffResetThresholdInMilliseconds)
36   }
38   destroy() {
39     if (this.resetTimeout) {
40       clearTimeout(this.resetTimeout)
41     }
42   }
44   didFailToFetchToken() {
45     this.incrementAttempts()
46   }
48   didClose() {
49     this.connected = false
51     this.incrementAttempts()
52   }
54   get isConnected(): boolean {
55     return this.connected
56   }
58   getBackoff(): number {
59     return this.getBackoffWithoutJitter() * this.getJitterFactor()
60   }
62   getBackoffWithoutJitter(): number {
63     const exponent = Math.max(this.attempts, 1)
64     const backoff = Math.pow(2, exponent) * 1000
66     return Math.min(backoff, MaxBackoffInMilliseconds)
67   }
69   getJitterFactor(): number {
70     return Math.random() * (MaximumJitterFactor - MinimumJitterFactor) + MinimumJitterFactor
71   }
73   get attemptCount(): number {
74     return this.attempts
75   }
77   incrementAttempts() {
78     this.attempts++
79   }
81   resetAttempts() {
82     this.attempts = 0
83   }