@@ -6,6 +6,7 @@ import Account from '../Account'
6
6
import { STATUS_ALLGOOD , STATUS_DISABLED , STATUS_ERROR , STATUS_SYNCING } from '../interfaces/Controller'
7
7
8
8
const INACTIVITY_TIMEOUT = 1000 * 7
9
+ const MAX_BACKOFF_INTERVAL = 1000 * 60 * 60 // 1 hour
9
10
const DEFAULT_SYNC_INTERVAL = 15
10
11
11
12
class AlarmManager {
@@ -31,18 +32,48 @@ class AlarmManager {
31
32
for ( let accountId of accounts ) {
32
33
const account = await Account . get ( accountId )
33
34
const data = account . getData ( )
35
+ const lastSync = data . lastSync || 0
36
+ const interval = data . syncInterval || DEFAULT_SYNC_INTERVAL
34
37
if ( data . scheduled ) {
35
38
this . ctl . scheduleSync ( accountId )
39
+ continue
40
+ }
41
+ if ( data . error && data . errorCount > 1 ) {
42
+ if ( Date . now ( ) > this . getBackoffInterval ( interval , data . errorCount , lastSync ) + lastSync ) {
43
+ this . ctl . scheduleSync ( accountId )
44
+ continue
45
+ }
46
+ continue
36
47
}
37
48
if (
38
- ! data . lastSync ||
39
49
Date . now ( ) >
40
- ( data . syncInterval || DEFAULT_SYNC_INTERVAL ) * 1000 * 60 + data . lastSync
50
+ interval * 1000 * 60 + data . lastSync
41
51
) {
42
52
this . ctl . scheduleSync ( accountId )
43
53
}
44
54
}
45
55
}
56
+
57
+ /**
58
+ * Calculates the backoff interval based on the synchronization interval and the error count.
59
+ *
60
+ * This method determines the delay before retrying a synchronization
61
+ * after one or more errors have occurred. It uses an exponential
62
+ * backoff algorithm with a cap at the maximum backoff interval.
63
+ *
64
+ * @param {number } interval - The synchronization interval in minutes.
65
+ * @param {number } errorCount - The number of consecutive errors encountered.
66
+ * @param {number } lastSync - The timestamp of when the last successful sync happened.
67
+ * @returns {number } - The calculated backoff interval in milliseconds.
68
+ */
69
+ getBackoffInterval ( interval , errorCount , lastSync ) {
70
+ const maxErrorCount = Math . log2 ( MAX_BACKOFF_INTERVAL / ( interval * 1000 * 60 ) )
71
+ if ( errorCount < maxErrorCount || lastSync + MAX_BACKOFF_INTERVAL > Date . now ( ) ) {
72
+ return Math . min ( MAX_BACKOFF_INTERVAL , interval * 1000 * 60 * Math . pow ( 2 , errorCount ) )
73
+ } else {
74
+ return MAX_BACKOFF_INTERVAL + MAX_BACKOFF_INTERVAL * ( errorCount - maxErrorCount )
75
+ }
76
+ }
46
77
}
47
78
48
79
export default class NativeController {
0 commit comments