ResilienceKit

0.4.0

AltiAntonov/ResilienceKit

What's New

ResilienceKit 0.4.0

2026-05-04T19:17:26Z

0.4.0

  • Added .retry(_:) for generic error-based retry predicates
  • Preserved default behavior of retrying all non-cancellation errors
  • Added fail-fast behavior for non-retryable errors
  • Added tests and documentation for selective retry behavior

ResilienceKit

Small async retry primitives for Swift with explicit attempts and terminal cancellation.

Swift version compatibility Platform compatibility MIT License Swift workflow

Features · Installation · Quick Start · When To Use · Good Fits · Weaker Fits · Runtime Semantics · Documentation · Testing

Features

  • async-first retry entry point with Retry { ... }
  • explicit .maxAttempts(_:) configuration
  • fixed delay support through .delay(_:)
  • exponential backoff and bounded jitter
  • retry predicates through .retry { ... }
  • 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.4.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(4)
.exponentialBackoff(
    baseDelay: .milliseconds(250),
    multiplier: 2,
    maxDelay: .seconds(5),
    jitter: .fraction(0.2)
)
.retry { error in
    error is URLError
}
.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 for loops
  • teams that want retry, fixed delay, backoff, and jitter behind one call-site shape
  • code that needs to retry transient errors while failing fast on permanent errors
  • small packages or apps that want focused retry behavior without unrelated dependencies

Weaker Fits

  • projects that need HTTP-specific retry helpers 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 1 are clamped to 1
  • .delay(_:) configures a fixed delay between failed attempts and defaults to .zero
  • .exponentialBackoff(baseDelay:multiplier:maxDelay:jitter:) configures growing retry delays
  • RetryJitter.fraction(_:) applies bounded randomness to reduce synchronized retries
  • .retry { ... } decides whether a non-cancellation error is retryable
  • the first attempt always starts immediately
  • delay is applied only between eligible retries, never after the final failed attempt
  • non-retryable errors are thrown immediately without delay or another attempt
  • cancellation before the first attempt prevents the operation from running
  • CancellationError is terminal and is rethrown without additional attempts
  • cancellation during delay is rethrown and no later attempt runs
  • all non-cancellation thrown errors are retried until attempts are exhausted

HTTP-specific retry helpers 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
  • exponential backoff progression
  • bounded jitter behavior
  • selective retry behavior
  • fail-fast behavior for non-retryable errors
  • 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

Description

  • Swift Tools 6.0.0
View More Packages from this Author

Dependencies

  • None
Last updated: Tue Jun 09 2026 02:01:26 GMT-0900 (Hawaii-Aleutian Daylight Time)