@@ -88,8 +88,12 @@ class ReconnectionManager {
8888 self . currentRetry += 1
8989
9090 if self . currentRetry < self . maxRetries {
91- // Calculate exponential backoff
92- let backoffSeconds = min ( pow ( 2.0 , Double ( currentRetry - 1 ) ) , 60.0 )
91+ // Calculate exponential backoff with jitter to prevent thundering herd
92+ let backoffSeconds = Self . calculateBackoff (
93+ attempt: self . currentRetry,
94+ baseDelay: 1.0 ,
95+ maxDelay: 60.0 ,
96+ jitterFactor: 0.3 )
9397 self . nextRetryTime = Date ( ) . addingTimeInterval ( backoffSeconds)
9498
9599 try ? await Task . sleep ( for: . seconds( backoffSeconds) )
@@ -110,15 +114,33 @@ class ReconnectionManager {
110114// MARK: - Exponential Backoff Calculator
111115
112116extension ReconnectionManager {
113- /// Calculate the next retry delay using exponential backoff
117+ /// Calculate the next retry delay using exponential backoff with jitter.
118+ ///
119+ /// Jitter prevents the "thundering herd" problem where many clients
120+ /// reconnect simultaneously after a server restart or network outage.
121+ /// The randomized delay spreads reconnection attempts over time,
122+ /// reducing server load spikes.
123+ ///
124+ /// - Parameters:
125+ /// - attempt: The current retry attempt number (1-indexed)
126+ /// - baseDelay: Initial delay in seconds (default: 1.0)
127+ /// - maxDelay: Maximum delay cap in seconds (default: 60.0)
128+ /// - jitterFactor: Randomization factor (0.0-1.0, default: 0.3)
129+ /// - Returns: Calculated delay with jitter applied
114130 static func calculateBackoff(
115131 attempt: Int ,
116132 baseDelay: TimeInterval = 1.0 ,
117- maxDelay: TimeInterval = 60.0 )
133+ maxDelay: TimeInterval = 60.0 ,
134+ jitterFactor: Double = 0.3 )
118135 -> TimeInterval
119136 {
120137 let exponentialDelay = baseDelay * pow( 2.0 , Double ( attempt - 1 ) )
121- return min ( exponentialDelay, maxDelay)
138+ let cappedDelay = min ( exponentialDelay, maxDelay)
139+
140+ // Apply jitter: add random value between 0 and jitterFactor * delay
141+ // This spreads reconnection attempts to prevent thundering herd
142+ let jitter = cappedDelay * jitterFactor * Double. random ( in: 0 ... 1 )
143+ return cappedDelay + jitter
122144 }
123145}
124146
0 commit comments