@@ -28,6 +28,9 @@ extension NetworkError: LocalizedError {
28
28
}
29
29
30
30
struct NetworkHelper {
31
+ static let maxRetryCount = 5
32
+ static let retryDelaySeconds = 2
33
+
31
34
static func getData( fromUrl url: URL , usingSession networkSession: NetworkSessionProtocol ) -> Pending < Data , Error > {
32
35
let fulfill = Fulfill < Data , Error > ( )
33
36
@@ -52,8 +55,9 @@ struct NetworkHelper {
52
55
static func sendRequest< T> ( _ request: URLRequest ,
53
56
converter: @escaping ( Data ) throws -> T ? ,
54
57
usingSession networkSession: NetworkSessionProtocol ) -> Pending < T , NetworkError > {
55
- #if NETWORK_DEBUG
58
+
56
59
let requestId = IterableUtil . generateUUID ( )
60
+ #if NETWORK_DEBUG
57
61
print ( )
58
62
print ( " ====================================================> " )
59
63
print ( " sending request: \( request) " )
@@ -73,29 +77,65 @@ struct NetworkHelper {
73
77
#endif
74
78
75
79
let fulfill = Fulfill < T , NetworkError > ( )
76
-
77
- networkSession. makeRequest ( request) { data, response, error in
78
- let result = createResultFromNetworkResponse ( data: data,
79
- converter: converter,
80
- response: response,
81
- error: error)
82
80
83
- switch result {
84
- case let . success( value) :
85
- #if NETWORK_DEBUG
86
- print ( " request with id: \( requestId) successfully sent, response: " )
87
- print ( value)
88
- #endif
89
- fulfill. resolve ( with: value)
90
- case let . failure( error) :
81
+ func sendRequestWithRetries( request: URLRequest , requestId: String , retriesLeft: Int ) {
82
+ networkSession. makeRequest ( request) { data, response, error in
83
+ let result = createResultFromNetworkResponse ( data: data,
84
+ converter: converter,
85
+ response: response,
86
+ error: error)
87
+ switch result {
88
+ case let . success( value) :
89
+ handleSuccess ( requestId: requestId, value: value)
90
+ case let . failure( error) :
91
+ handleFailure ( requestId: requestId, request: request, error: error, retriesLeft: retriesLeft)
92
+ }
93
+ }
94
+ }
95
+
96
+ func handleSuccess( requestId: String , value: T ) {
97
+ #if NETWORK_DEBUG
98
+ print ( " request with id: \( requestId) successfully sent, response: " )
99
+ print ( value)
100
+ #endif
101
+ fulfill. resolve ( with: value)
102
+ }
103
+
104
+ func handleFailure( requestId: String , request: URLRequest , error: NetworkError , retriesLeft: Int ) {
105
+ if shouldRetry ( error: error, retriesLeft: retriesLeft) {
106
+ retryRequest ( requestId: requestId, request: request, error: error, retriesLeft: retriesLeft)
107
+ } else {
91
108
#if NETWORK_DEBUG
92
109
print ( " request with id: \( requestId) errored " )
93
110
print ( error)
94
111
#endif
95
112
fulfill. reject ( with: error)
96
113
}
114
+
97
115
}
98
116
117
+ func shouldRetry( error: NetworkError , retriesLeft: Int ) -> Bool {
118
+ return error. httpStatusCode ?? 0 >= 500 && retriesLeft > 0
119
+ }
120
+
121
+ func retryRequest( requestId: String , request: URLRequest , error: NetworkError , retriesLeft: Int ) {
122
+ #if NETWORK_DEBUG
123
+ print ( " retry attempt: \( maxRetryCount- retriesLeft+ 1 ) for url: \( request. url? . absoluteString ?? " " ) " )
124
+ print ( error)
125
+ #endif
126
+
127
+ var delay : DispatchTimeInterval = . seconds( 0 )
128
+ if retriesLeft <= 3 {
129
+ delay = . seconds( retryDelaySeconds)
130
+ }
131
+
132
+ DispatchQueue . global ( ) . asyncAfter ( deadline: . now( ) + delay) {
133
+ sendRequestWithRetries ( request: request, requestId: requestId, retriesLeft: retriesLeft - 1 )
134
+ }
135
+ }
136
+
137
+ sendRequestWithRetries ( request: request, requestId: requestId, retriesLeft: maxRetryCount)
138
+
99
139
return fulfill
100
140
}
101
141
0 commit comments