AltiAntonov/ResilienceKit
<div align="center"> <h1>ResilienceKit</h1> <p><strong>Small async retry primitives for Swift with explicit attempts and terminal cancellation.</strong></p> <p> <a href="https://swiftpackageindex.com/AltiAntonov/ResilienceKit"> <img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FAltiAntonov%2FResilienceKit%2Fbadge%3Ftype%3Dswift-versions" alt="Swift version compatibility"> </a> <a href="https://swiftpackageindex.com/AltiAntonov/ResilienceKit"> <img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FAltiAntonov%2FResilienceKit%2Fbadge%3Ftype%3Dplatforms" alt="Platform compatibility"> </a> <img src="https://img.shields.io/badge/License-MIT-34C759" alt="MIT License"> <a href="https://github.com/AltiAntonov/ResilienceKit/actions/workflows/swift.yml"><img src="https://github.com/AltiAntonov/ResilienceKit/actions/workflows/swift.yml/badge.svg" alt="Swift workflow"></a> </p> <p> <a href="#features">Features</a> · <a href="#installation">Installation</a> · <a href="#quick-start">Quick Start</a> · <a href="#when-to-use">When To Use</a> · <a href="#good-fits">Good Fits</a> · <a href="#weaker-fits">Weaker Fits</a> · <a href="#runtime-semantics">Runtime Semantics</a> · <a href="#documentation">Documentation</a> · <a href="#testing">Testing</a> </p> </div>
Features
- async-first retry entry point with
Retry { ... } - explicit
.maxAttempts(_:)configuration - fixed delay support through
.delay(_:) - terminal cancellation that is not retried
- small surface area intended to grow in layers
The current public API is intentionally centered on:
Retry
Installation
Add ResilienceKit to your Swift Package Manager dependencies:
dependencies: [
.package(url: "https://github.com/AltiAntonov/ResilienceKit.git", from: "0.1.0")
]Then add the product to your target:
.target(
name: "YourApp",
dependencies: [
.product(name: "ResilienceKit", package: "ResilienceKit")
]
)Quick Start
import ResilienceKit
let value = try await Retry {
try await fetchProfile()
}
.maxAttempts(3)
.delay(.seconds(1))
.run()maxAttempts(_:) always means total executions, including the first call.
When To Use
Use ResilienceKit when you want retry behavior to be explicit, readable, and reusable instead of re-implementing ad hoc retry loops around async work.
It is a strong fit when the first thing you need is a small retry primitive, not a full resilience framework.
Good Fits
- app and SDK code that wraps async network requests
- codebases that want one obvious retry call site instead of repeated
forloops - teams that want to add backoff and jitter later without changing the entry-point shape
- small packages or apps that want focused retry behavior without unrelated dependencies
Weaker Fits
- projects that need backoff, jitter, or retry predicates today
- systems that already require a broader resilience stack such as circuit breaking or rate limiting
- sync-only code paths
- packages that need broad platform coverage below iOS 17 or macOS 14 right now
Runtime Semantics
.maxAttempts(_:)controls the total number of attempts, not retries-after-the-first- values below
1are clamped to1 .delay(_:)configures a fixed delay between failed attempts and defaults to.zero- the first attempt always starts immediately
- delay is applied only between eligible retries, never after the final failed attempt
CancellationErroris terminal and is rethrown without additional attempts- all non-cancellation thrown errors are retried until attempts are exhausted
Backoff, jitter, and retry predicates are intentionally deferred to later releases.
Documentation
The package now includes a DocC catalog in Sources/ResilienceKit/ResilienceKit.docc.
Once Swift Package Index processes .spi.yml, hosted documentation should appear on the package page automatically.
Testing
The package uses Swift Testing.
Current coverage verifies:
- first-attempt success
- retry-until-success behavior
- fixed delay between failed attempts
- no trailing delay after the final failed attempt
- exact call count on persistent failure
- clamp behavior for invalid attempt counts
- terminal cancellation from both pre-cancelled tasks, thrown
CancellationError, and cancellation during delay
Package Metadata
Repository: AltiAntonov/ResilienceKit
Stars: 0
Forks: 0
Open issues: 0
Default branch: main
Primary language: swift
License: MIT
README: README.md