From 1a5e99b778fb0bdd092d60d648fbba7198c9f35a Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 6 Mar 2026 16:50:32 +0400 Subject: [PATCH] docs: update `README.md` --- README.md | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ffb3389..b32b1be 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,9 @@ Typhoon is a modern, lightweight Swift framework that provides elegant and robus ๐ŸŽฏ **Type-Safe** - Leverages Swift's type system for compile-time safety ๐Ÿ”ง **Configurable** - Flexible retry parameters for any use case ๐Ÿ“ฑ **Cross-Platform** - Works on iOS, macOS, tvOS, watchOS, and visionOS -โšก **Lightweight** - Minimal footprint with zero dependencies +โšก **Lightweight** - Minimal footprint with zero dependencies +๐Ÿงพ **Pluggable Logging** โ€“ Integrates with OSLog or custom loggers +๐ŸŒ **URLSession Integration** โ€“ Retry network requests with a single parameter ๐Ÿงช **Well Tested** - Comprehensive test coverage ## Table of Contents @@ -34,6 +36,10 @@ Typhoon is a modern, lightweight Swift framework that provides elegant and robus - [Constant Strategy](#constant-strategy) - [Exponential Strategy](#exponential-strategy) - [Exponential with Jitter Strategy](#exponential-with-jitter-strategy) + - [Custom Strategy](#custom-strategy) + - [Chain Strategy](#chain-strategy) +- [Logging](#logging) +- [URLSession Integration](urlsession-integration) - [Common Use Cases](#common-use-cases) - [Communication](#communication) - [Documentation](#documentation) @@ -95,7 +101,7 @@ do { ### Retry Strategies -Typhoon provides three powerful retry strategies to handle different failure scenarios: +Typhoon provides six powerful retry strategies to handle different failure scenarios: ```swift /// A retry strategy with a constant number of attempts and fixed duration between retries. @@ -120,6 +126,15 @@ case exponential( case custom(retry: UInt, strategy: IRetryDelayStrategy) ``` +Additionally, Typhoon allows composing multiple retry strategies into a single policy using a chained strategy: + +``` +RetryPolicyStrategy.chain([ + .constant(retry: 2, dispatchDuration: .seconds(1)), + .exponential(retry: 3, dispatchDuration: .seconds(2)) +]) +``` + ### Constant Strategy Best for scenarios where you want predictable, fixed delays between retries: @@ -315,6 +330,93 @@ The total retry count is calculated automatically from the sum of all entries Each strategy in the chain uses **local indexing**, meaning every phase starts its delay calculation from zero. This ensures each strategy behaves predictably regardless of its position in the chain. +## Logging + +Typhoon provides a lightweight logging abstraction that allows you to integrate retry diagnostics into your existing logging system. + +The framework defines a simple ILogger protocol: + +``` +public protocol ILogger: Sendable { + func info(_ message: String) + func warning(_ message: String) + func error(_ message: String) +} +``` + +You can plug in any logging framework by implementing this protocol. + +### Using Apple's OSLog + +Typhoon includes built-in support for Apple's OSLog system via Logger: + +``` +import Typhoon +import OSLog + +let logger = Logger(subsystem: "com.example.network", category: "retry") + +let retryService = RetryPolicyService( + strategy: .exponential(retry: 3, dispatchDuration: .seconds(1)), + logger: logger +) +``` + +All retry attempts, failures, and final errors will be reported through the provided logger. + +You can also integrate third-party loggers like SwiftLog or custom analytics systems. + +## URLSession Integration + +Typhoon provides built-in integration with URLSession, allowing you to apply retry policies directly to network requests with minimal boilerplate. + +Instead of wrapping network calls manually, you can call retry-enabled methods directly on URLSession. + +### Fetch Data with Retry + +``` +import Typhoon + +let (data, response) = try await URLSession.shared.data( + from: URL(string: "https://api.example.com/users")!, + retryPolicy: .exponential( + retry: 3, + jitterFactor: 0.1, + dispatchDuration: .seconds(1) + ) +) +``` + +### Using URLRequest + +``` +var request = URLRequest(url: URL(string: "https://api.example.com/users")!) +request.httpMethod = "GET" + +let (data, response) = try await URLSession.shared.data( + for: request, + retryPolicy: .constant(retry: 3, dispatchDuration: .seconds(1)) +) +``` + +### Upload Requests + +``` +let (data, response) = try await URLSession.shared.upload( + for: request, + from: bodyData, + retryPolicy: .exponential(retry: 3, dispatchDuration: .seconds(1)) +) +``` + +### Download Requests + +``` +let (fileURL, response) = try await URLSession.shared.download( + for: request, + retryPolicy: .exponential(retry: 4, dispatchDuration: .seconds(2)) +) +``` ## Common Use Cases