Skip to content

Commit 8792ccd

Browse files
authored
Merge pull request #36 from denis-obukhov/master
Add the ability to retry a request
2 parents abc8c6e + f09de00 commit 8792ccd

File tree

3 files changed

+44
-12
lines changed

3 files changed

+44
-12
lines changed

Sources/Networking/Calls/NetworkingClient+Requests.swift

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,27 @@ public extension NetworkingClient {
3232

3333
internal func request(_ httpVerb: HTTPVerb, _ route: String, params: Params = Params()) -> NetworkingRequest {
3434
let req = NetworkingRequest()
35-
req.baseURL = baseURL
36-
req.logLevels = logLevels
37-
req.headers = headers
3835
req.httpVerb = httpVerb
3936
req.route = route
4037
req.params = params
41-
req.parameterEncoding = parameterEncoding
42-
req.sessionConfiguration = sessionConfiguration
43-
req.timeout = timeout
38+
39+
let updateRequest = { [weak req, weak self] in
40+
guard let self = self else { return }
41+
req?.baseURL = self.baseURL
42+
req?.logLevels = self.logLevels
43+
req?.headers = self.headers
44+
req?.parameterEncoding = self.parameterEncoding
45+
req?.sessionConfiguration = self.sessionConfiguration
46+
req?.timeout = self.timeout
47+
}
48+
updateRequest()
49+
req.requestRetrier = { [weak self] in
50+
self?.requestRetrier?($0, $1)?
51+
.handleEvents(receiveOutput: { _ in
52+
updateRequest()
53+
})
54+
.eraseToAnyPublisher()
55+
}
4456
return req
4557
}
4658
}

Sources/Networking/NetworkingClient.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import Foundation
22
import Combine
33

4-
public struct NetworkingClient {
5-
4+
public class NetworkingClient {
65
/**
76
Instead of using the same keypath for every call eg: "collection",
87
this enables to use a default keypath for parsing collections.
@@ -15,6 +14,7 @@ public struct NetworkingClient {
1514
public var parameterEncoding = ParameterEncoding.urlEncoded
1615
public var timeout: TimeInterval?
1716
public var sessionConfiguration = URLSessionConfiguration.default
17+
public var requestRetrier: NetworkRequestRetrier?
1818

1919
/**
2020
Prints network calls to the console.

Sources/Networking/NetworkingRequest.swift

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import Foundation
99
import Combine
1010

11+
public typealias NetworkRequestRetrier = (_ request: URLRequest, _ error: Error) -> AnyPublisher<Void, Error>?
12+
1113
public class NetworkingRequest: NSObject {
1214

1315
var parameterEncoding = ParameterEncoding.urlEncoded
@@ -25,7 +27,9 @@ public class NetworkingRequest: NSObject {
2527
var timeout: TimeInterval?
2628
let progressPublisher = PassthroughSubject<Progress, Error>()
2729
var sessionConfiguration: URLSessionConfiguration?
28-
30+
var requestRetrier: NetworkRequestRetrier?
31+
private let maxRetryCount = 3
32+
2933
public func uploadPublisher() -> AnyPublisher<(Data?, Progress), Error> {
3034

3135
guard let urlRequest = buildURLRequest() else {
@@ -63,9 +67,12 @@ public class NetworkingRequest: NSObject {
6367
return Publishers.Merge(callPublisher, progressPublisher2)
6468
.receive(on: DispatchQueue.main).eraseToAnyPublisher()
6569
}
66-
70+
6771
public func publisher() -> AnyPublisher<Data, Error> {
68-
72+
publisher(retryCount: maxRetryCount)
73+
}
74+
75+
private func publisher(retryCount: Int) -> AnyPublisher<Data, Error> {
6976
guard let urlRequest = buildURLRequest() else {
7077
return Fail(error: NetworkingError.unableToParseRequest as Error)
7178
.eraseToAnyPublisher()
@@ -87,7 +94,20 @@ public class NetworkingRequest: NSObject {
8794
}
8895
}
8996
return data
90-
}.mapError { error -> NetworkingError in
97+
}.tryCatch({ [weak self, urlRequest] error -> AnyPublisher<Data, Error> in
98+
guard
99+
let self = self,
100+
retryCount > 1,
101+
let retryPublisher = self.requestRetrier?(urlRequest, error)
102+
else {
103+
throw error
104+
}
105+
return retryPublisher
106+
.flatMap { _ -> AnyPublisher<Data, Error> in
107+
self.publisher(retryCount: retryCount - 1)
108+
}
109+
.eraseToAnyPublisher()
110+
}).mapError { error -> NetworkingError in
91111
return NetworkingError(error: error)
92112
}.receive(on: DispatchQueue.main).eraseToAnyPublisher()
93113
}

0 commit comments

Comments
 (0)