Skip to content

Commit 4e05ed2

Browse files
committed
fixes retry handling
1 parent 8e65cfc commit 4e05ed2

File tree

3 files changed

+41
-27
lines changed

3 files changed

+41
-27
lines changed

CHANGELOG.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [1.0] - unreleased
8+
## [1.0.1] - 2023-05-09
9+
10+
### Fixed
11+
* Retry handling for an unauthorized request
12+
13+
## [1.0] - 2023-04-25
914

1015
Initial Release

Sources/Network/Core/NetworkManager.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class NetworkManager {
4040
.flatMap { [self] endpoint in
4141
urlSession.publisher(for: endpoint)
4242
}
43-
.retry(1, when: { apiError in
43+
.retryOnce(if: { apiError in
4444
switch apiError {
4545
case .validationError(let httpStatusCode, _):
4646
return httpStatusCode == .unauthorized
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Publisher+RetryWhenDoBefore.swift
2+
// Publisher+RetryOnceIfDoBefore.swift
33
//
44
//
55
// Created by Andreas Osberghaus on 2023-02-27.
@@ -8,31 +8,40 @@
88
import Foundation
99
import Combine
1010

11-
extension Publisher {
12-
func retryOnly<Upstream: Publisher>(
13-
upstream: Upstream,
14-
retries: Int,
15-
when predicate: @escaping (Upstream.Failure) -> Bool,
16-
doBefore handler: () -> Void
17-
) -> AnyPublisher<Upstream.Output, Upstream.Failure> {
11+
extension Publishers {
12+
struct RetryOnceIf<P: Publisher>: Publisher {
13+
typealias Output = P.Output
14+
typealias Failure = P.Failure
15+
16+
let publisher: P
17+
let times: Int
18+
let condition: (P.Failure) -> Bool
19+
let doBefore: () -> Void
1820

19-
upstream
20-
.map { output -> Result<Upstream.Output, Upstream.Failure> in .success(output) }
21-
.catch { error -> AnyPublisher<Result<Upstream.Output, Upstream.Failure>, Upstream.Failure> in
22-
if predicate(error) {
23-
return Fail(error: error).eraseToAnyPublisher()
24-
} else {
25-
return Just(.failure(error))
26-
.setFailureType(to: Upstream.Failure.self)
27-
.eraseToAnyPublisher()
21+
func receive<S>(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input {
22+
guard times > 0 else {
23+
return publisher.receive(subscriber: subscriber)
2824
}
29-
}
30-
.retry(retries)
31-
.flatMap { result in result.publisher }
32-
.eraseToAnyPublisher()
33-
}
3425

35-
func retry(_ retries: Int, when predicate: @escaping (Failure) -> Bool, doBefore handler: () -> Void) -> AnyPublisher<Output, Failure> {
36-
return retryOnly(upstream: self, retries: retries, when: predicate, doBefore: handler)
37-
}
26+
publisher.catch { (error: P.Failure) -> AnyPublisher<Output, Failure> in
27+
if condition(error) {
28+
doBefore()
29+
return RetryOnceIf(
30+
publisher: publisher,
31+
times: times - 1,
32+
condition: condition,
33+
doBefore: doBefore
34+
).eraseToAnyPublisher()
35+
} else {
36+
return Fail(error: error).eraseToAnyPublisher()
37+
}
38+
}.receive(subscriber: subscriber)
39+
}
40+
}
41+
}
42+
43+
extension Publisher {
44+
func retryOnce(if condition: @escaping (Failure) -> Bool, doBefore: @escaping () -> Void) -> Publishers.RetryOnceIf<Self> {
45+
Publishers.RetryOnceIf(publisher: self, times: 1, condition: condition, doBefore: doBefore)
46+
}
3847
}

0 commit comments

Comments
 (0)