Skip to content

Commit a4cf2c2

Browse files
committed
chore: update README.md
1 parent 6dab396 commit a4cf2c2

1 file changed

Lines changed: 294 additions & 32 deletions

File tree

README.md

Lines changed: 294 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,101 @@
1-
![Typhoon: a service for retry policies](https://raw.githubusercontent.com/space-code/typhoon/dev/Resources/typhoon.png)
1+
![A powerful retry policy service for Swift](./Resources/typhoon.png)
22

33
<h1 align="center" style="margin-top: 0px;">typhoon</h1>
44

55
<p align="center">
66
<a href="https://github.com/space-code/typhoon/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/space-code/typhoon?style=flat"></a>
77
<a href="https://swiftpackageindex.com/space-code/typhoon"><img alt="Swift Compatibility" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fspace-code%2Ftyphoon%2Fbadge%3Ftype%3Dswift-versions"></a>
88
<a href="https://swiftpackageindex.com/space-code/typhoon"><img alt="Platform Compatibility" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fspace-code%2Ftyphoon%2Fbadge%3Ftype%3Dplatforms"/></a>
9-
<a href="https://github.com/space-code/typhoon"><img alt="CI" src="https://github.com/space-code/Typhoon/actions/workflows/ci.yml/badge.svg?branch=main"></a>
9+
<a href="https://github.com/space-code/typhoon/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/space-code/Typhoon/actions/workflows/ci.yml/badge.svg?branch=main"></a>
1010
<a href="https://github.com/apple/swift-package-manager" alt="typhoon on Swift Package Manager" title="typhoon on Swift Package Manager"><img src="https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg" /></a>
1111
<a href="https://codecov.io/gh/space-code/typhoon"><img src="https://codecov.io/gh/space-code/typhoon/graph/badge.svg?token=u89doKdnec"/></a>
1212
</p>
1313

1414
## Description
15-
`Typhoon` is a service for retry policies.
15+
Typhoon is a modern, lightweight Swift framework that provides elegant and robust retry policies for asynchronous operations. Built with Swift's async/await concurrency model, it helps you handle transient failures gracefully with configurable retry strategies.
16+
17+
## Features
18+
19+
**Multiple Retry Strategies** - Constant, exponential, and exponential with jitter
20+
**Async/Await Native** - Built for modern Swift concurrency
21+
🎯 **Type-Safe** - Leverages Swift's type system for compile-time safety
22+
🔧 **Configurable** - Flexible retry parameters for any use case
23+
📱 **Cross-Platform** - Works on iOS, macOS, tvOS, watchOS, and visionOS
24+
**Lightweight** - Minimal footprint with zero dependencies
25+
🧪 **Well Tested** - Comprehensive test coverage
26+
27+
## Table of Contents
1628

17-
- [Usage](#usage)
1829
- [Requirements](#requirements)
1930
- [Installation](#installation)
31+
- [Quick Start](#quick-start)
32+
- [Usage](#usage)
33+
- [Retry Strategies](#retry-strategies)
34+
- [Constant Strategy](#constant-strategy)
35+
- [Exponential Strategy](#exponential-strategy)
36+
- [Exponential with Jitter Strategy](#exponential-with-jitter-strategy)
37+
- [Common Use Cases](#common-use-cases)
38+
- [Error Handling](#error-handling)
2039
- [Communication](#communication)
2140
- [Contributing](#contributing)
41+
- [Development Setup](#development-setup)
2242
- [Author](#author)
2343
- [License](#license)
2444

45+
## Requirements
46+
47+
| Platform | Minimum Version |
48+
|-----------|----------------|
49+
| iOS | 13.0+ |
50+
| macOS | 10.15+ |
51+
| tvOS | 13.0+ |
52+
| watchOS | 6.0+ |
53+
| visionOS | 1.0+ |
54+
| Xcode | 15.3+ |
55+
| Swift | 5.10+ |
56+
57+
## Installation
58+
59+
### Swift Package Manager
60+
61+
Add the following dependency to your `Package.swift`:
62+
63+
```swift
64+
dependencies: [
65+
.package(url: "https://github.com/space-code/typhoon.git", from: "1.3.0")
66+
]
67+
```
68+
69+
Or add it through Xcode:
70+
71+
1. File > Add Package Dependencies
72+
2. Enter package URL: `https://github.com/space-code/typhoon.git`
73+
3. Select version requirements
74+
75+
## Quick Start
76+
77+
```swift
78+
import Typhoon
79+
80+
let retryService = RetryPolicyService(
81+
strategy: .constant(retry: 3, duration: .seconds(1))
82+
)
83+
84+
do {
85+
let result = try await retryService.retry {
86+
try await fetchDataFromAPI()
87+
}
88+
print("✅ Success: \(result)")
89+
} catch {
90+
print("❌ Failed after retries: \(error)")
91+
}
92+
```
93+
2594
## Usage
2695

27-
`Typhoon` provides three retry policy strategies:
96+
### Retry Strategies
97+
98+
Typhoon provides three powerful retry strategies to handle different failure scenarios:
2899

29100
```swift
30101
/// A retry strategy with a constant number of attempts and fixed duration between retries.
@@ -34,60 +105,251 @@ case constant(retry: Int, duration: DispatchTimeInterval)
34105
case exponential(retry: Int, multiplier: Double = 2.0, duration: DispatchTimeInterval)
35106

36107
/// A retry strategy with exponential increase in duration between retries and added jitter.
37-
case exponentialWithJitter(retry: Int, jitterFactor: Double = 0.1, maxInterval: UInt64? = 60, multiplier: Double = 2.0, duration: DispatchTimeInterval)
108+
case exponentialWithJitter(
109+
retry: Int,
110+
jitterFactor: Double = 0.1,
111+
maxInterval: UInt64? = 60,
112+
multiplier: Double = 2.0,
113+
duration: DispatchTimeInterval
114+
)
38115
```
39116

40-
Create a `RetryPolicyService` instance and pass a desired strategy like this:
117+
### Constant Strategy
118+
119+
Best for scenarios where you want predictable, fixed delays between retries:
41120

42121
```swift
43122
import Typhoon
44123

45-
let retryPolicyService = RetryPolicyService(strategy: .constant(retry: 10, duration: .seconds(1)))
124+
// Retry up to 5 times with 2 seconds between each attempt
125+
let service = RetryPolicyService(
126+
strategy: .constant(retry: 5, duration: .seconds(2))
127+
)
46128

47129
do {
48-
_ = try await retryPolicyService.retry {
49-
// Some logic here ...
50-
}
130+
let data = try await service.retry {
131+
try await URLSession.shared.data(from: url)
132+
}
51133
} catch {
52-
// Catch an error here ...
134+
print("Failed after 5 attempts")
53135
}
54136
```
55137

56-
## Requirements
138+
**Retry Timeline:**
139+
- Attempt 1: Immediate
140+
- Attempt 2: After 2 seconds
141+
- Attempt 3: After 2 seconds
142+
- Attempt 4: After 2 seconds
143+
- Attempt 5: After 2 seconds
57144

58-
- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+ / visionOS 1.0+
59-
- Xcode 15.3
60-
- Swift 5.10
145+
### Exponential Strategy
61146

62-
## Installation
63-
### Swift Package Manager
147+
Ideal for avoiding overwhelming a failing service by progressively increasing wait times:
64148

65-
The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but `typhoon` does support its use on supported platforms.
149+
```swift
150+
import Typhoon
66151

67-
Once you have your Swift package set up, adding `typhoon` as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`.
152+
// Retry up to 4 times with exponentially increasing delays
153+
let service = RetryPolicyService(
154+
strategy: .exponential(
155+
retry: 4,
156+
multiplier: 2.0,
157+
duration: .seconds(1)
158+
)
159+
)
160+
161+
do {
162+
let response = try await service.retry {
163+
try await performNetworkRequest()
164+
}
165+
} catch {
166+
print("Request failed after exponential backoff")
167+
}
168+
```
169+
170+
**Retry Timeline:**
171+
- Attempt 1: Immediate
172+
- Attempt 2: After 1 second (1 × 2⁰)
173+
- Attempt 3: After 2 seconds (1 × 2¹)
174+
- Attempt 4: After 4 seconds (1 × 2²)
175+
176+
### Exponential with Jitter Strategy
177+
178+
The most sophisticated strategy, adding randomization to prevent thundering herd problems:
68179

69180
```swift
70-
dependencies: [
71-
.package(url: "https://github.com/space-code/typhoon.git", .upToNextMajor(from: "1.3.0"))
72-
]
181+
import Typhoon
182+
183+
// Retry with exponential backoff, jitter, and maximum interval cap
184+
let service = RetryPolicyService(
185+
strategy: .exponentialWithJitter(
186+
retry: 5,
187+
jitterFactor: 0.2, // Add ±20% randomization
188+
maxInterval: 30, // Cap at 30 seconds
189+
multiplier: 2.0,
190+
duration: .seconds(1)
191+
)
192+
)
193+
194+
do {
195+
let result = try await service.retry {
196+
try await connectToDatabase()
197+
}
198+
} catch {
199+
print("Connection failed after sophisticated retry attempts")
200+
}
201+
```
202+
203+
**Benefits of Jitter:**
204+
- Prevents multiple clients from retrying simultaneously
205+
- Reduces load spikes on recovering services
206+
- Improves overall system resilience
207+
208+
## Common Use Cases
209+
210+
### Network Requests
211+
212+
```swift
213+
import Typhoon
214+
215+
class APIClient {
216+
private let retryService = RetryPolicyService(
217+
strategy: .exponential(retry: 3, duration: .milliseconds(500))
218+
)
219+
220+
func fetchUser(id: String) async throws -> User {
221+
try await retryService.retry {
222+
let (data, _) = try await URLSession.shared.data(
223+
from: URL(string: "https://api.example.com/users/\(id)")!
224+
)
225+
return try JSONDecoder().decode(User.self, from: data)
226+
}
227+
}
228+
}
229+
```
230+
231+
### Database Operations
232+
233+
```swift
234+
import Typhoon
235+
236+
class DatabaseManager {
237+
private let retryService = RetryPolicyService(
238+
strategy: .exponentialWithJitter(
239+
retry: 5,
240+
jitterFactor: 0.15,
241+
maxInterval: 60,
242+
duration: .seconds(1)
243+
)
244+
)
245+
246+
func saveRecord(_ record: Record) async throws {
247+
try await retryService.retry {
248+
try await database.insert(record)
249+
}
250+
}
251+
}
252+
```
253+
254+
### File Operations
255+
256+
```swift
257+
import Typhoon
258+
259+
class FileService {
260+
private let retryService = RetryPolicyService(
261+
strategy: .constant(retry: 3, duration: .milliseconds(100))
262+
)
263+
264+
func writeFile(data: Data, to path: String) async throws {
265+
try await retryService.retry {
266+
try data.write(to: URL(fileURLWithPath: path))
267+
}
268+
}
269+
}
270+
```
271+
272+
### Third-Party Service Integration
273+
274+
```swift
275+
import Typhoon
276+
277+
class PaymentService {
278+
private let retryService = RetryPolicyService(
279+
strategy: .exponential(
280+
retry: 4,
281+
multiplier: 1.5,
282+
duration: .seconds(2)
283+
)
284+
)
285+
286+
func processPayment(amount: Decimal) async throws -> PaymentResult {
287+
try await retryService.retry {
288+
try await paymentGateway.charge(amount: amount)
289+
}
290+
}
291+
}
292+
```
293+
294+
## Error Handling
295+
296+
Typhoon preserves the original error from your operation after all retry attempts are exhausted:
297+
298+
```swift
299+
import Typhoon
300+
301+
let service = RetryPolicyService(
302+
strategy: .constant(retry: 3, duration: .seconds(1))
303+
)
304+
305+
do {
306+
try await service.retry {
307+
throw NetworkError.serverUnavailable
308+
}
309+
} catch let error as NetworkError {
310+
// Handle specific error type
311+
print("Network error: \(error)")
312+
} catch {
313+
// Handle other errors
314+
print("Unexpected error: \(error)")
315+
}
73316
```
74317

75318
## Communication
76-
- If you **found a bug**, open an issue.
77-
- If you **have a feature request**, open an issue.
78-
- If you **want to contribute**, submit a pull request.
319+
320+
- 🐛 **Found a bug?** [Open an issue](https://github.com/space-code/typhoon/issues/new)
321+
- 💡 **Have a feature request?** [Open an issue](https://github.com/space-code/typhoon/issues/new)
322+
-**Questions?** [Start a discussion](https://github.com/space-code/typhoon/discussions)
323+
- 🔒 **Security issue?** Email nv3212@gmail.com
79324

80325
## Contributing
81-
Bootstrapping development environment
82326

83-
```
327+
We love contributions! Please feel free to help out with this project. If you see something that could be made better or want a new feature, open up an issue or send a Pull Request.
328+
329+
### Development Setup
330+
331+
Bootstrap the development environment:
332+
333+
```bash
84334
make bootstrap
85335
```
86336

87-
Please feel free to help out with this project! If you see something that could be made better or want a new feature, open up an issue or send a Pull Request!
88-
89337
## Author
90-
Nikita Vasilev, nv3212@gmail.com
338+
339+
**Nikita Vasilev**
340+
- Email: nv3212@gmail.com
341+
- GitHub: [@ns-vasilev](https://github.com/ns-vasilev)
91342

92343
## License
93-
typhoon is available under the MIT license. See the LICENSE file for more info.
344+
345+
Typhoon is released under the MIT license. See [LICENSE](https://github.com/space-code/typhoon/blob/main/LICENSE) for details.
346+
347+
---
348+
349+
<div align="center">
350+
351+
**[⬆ back to top](#typhoon)**
352+
353+
Made with ❤️ by [space-code](https://github.com/space-code)
354+
355+
</div>

0 commit comments

Comments
 (0)