Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
swiftuiux committed Jul 23, 2024
1 parent 86917b6 commit 2a6a1f0
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 101 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import PackageDescription

let package = Package(
name: "retry-policy-service",
platforms: [.macOS(.v12), .iOS(.v15), .watchOS(.v8), .tvOS(.v15)],
platforms: [.macOS(.v11), .iOS(.v14), .watchOS(.v8), .tvOS(.v15)],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
Expand Down
72 changes: 0 additions & 72 deletions Sources/retry-policy-service/RetryIterator.swift

This file was deleted.

65 changes: 55 additions & 10 deletions Sources/retry-policy-service/RetryService.swift
Original file line number Diff line number Diff line change
@@ -1,34 +1,79 @@
//
// RetryService.swift
//
// RetryIterator.swift
//
//
// Created by Igor on 06.03.2023.
//

import Foundation


/// Generate sequence of time delays between retries depending on retry strategy
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
public struct RetryService: Sequence{
// RetryService Definition and Implementation
@available(iOS 14.0, macOS 11.0, tvOS 15.0, watchOS 8.0, *)
public struct RetryService: Sequence {

/// Default service
static let `default` = RetryService(strategy: .exponential())

/// Retry strategy
public let strategy: Strategy

/// - Parameter strategy: Retry strategy ``RetryService.Strategy``
public init(strategy: Strategy){
public init(strategy: Strategy) {
self.strategy = strategy
}

/// - Returns: Retry delays iterator
public func makeIterator() -> RetryIterator {
return RetryIterator(service: self)
}
}


/// Retry iterator
@available(iOS 14.0, macOS 11.0, tvOS 15.0, watchOS 8.0, *)
public struct RetryIterator: IteratorProtocol {

/// Current amount of retries
public private(set) var retries: UInt = 0

/// Retry strategy
public let strategy: Strategy

/// A time after which stop producing sequence
public let deadline: DispatchTime

/// - Parameter service: Retry service ``RetryService``
init(service: RetryService) {
self.strategy = service.strategy
self.deadline = .now() + strategy.timeout.toDispatchTimeInterval()
}

/// Returns the next delay amount in nanoseconds, or `nil`.
public mutating func next() -> UInt64? {
guard isValid else { return nil }
defer { retries += 1 }

switch strategy {
case .constant(_, let duration, _):
if let value = duration.toDouble() {
let delay = value * 1e+9
return UInt64(delay)
}
case .exponential(_, let multiplier, let duration, _):
if let duration = duration.toDouble() {
let value = duration * pow(multiplier, Double(retries))
let delay = value * 1e+9
return UInt64(delay)
}
}
return nil
}

/// Validate current iteration
var isValid: Bool {
guard deadline >= .now() else { return false }
let max = strategy.maximumRetries
guard max > retries && max != 0 else { return false }
return true
}
}
}
35 changes: 18 additions & 17 deletions Sources/retry-policy-service/Strategy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,45 @@ import Foundation
public extension RetryService{

/// Retry strategy
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
@available(iOS 14.0, macOS 11.0, tvOS 15.0, watchOS 8.0, *)
enum Strategy {

/// constant delay between retries
/// Constant delay between retries
case constant(
retry : UInt = 5,
retry: UInt = 5,
duration: DispatchTimeInterval = .seconds(2),
timeout: DispatchTimeInterval = .seconds(Int.max)
)

/// Exponential backoff is a strategy in which you increase the delays between retries.
case exponential(
retry : UInt = 3,
retry: UInt = 3,
multiplier: Double = 2.0,
duration: DispatchTimeInterval = .seconds(2),
timeout: DispatchTimeInterval = .seconds(Int.max)
)

/// Max amount of retries
var maximumRetries: UInt{
switch self{
case .constant(let retry, _, _) : return retry
case .exponential(let retry, _, _, _) : return retry
var maximumRetries: UInt {
switch self {
case .constant(let retry, _, _): return retry
case .exponential(let retry, _, _, _): return retry
}
}

/// Duration between retries For .exponential multiply on the amount of the current retries
var duration: DispatchTimeInterval{
switch self{
case .constant(_, let duration, _) : return duration
case .exponential(_, _, let duration, _) : return duration
/// Duration between retries
var duration: DispatchTimeInterval {
switch self {
case .constant(_, let duration, _): return duration
case .exponential(_, _, let duration, _): return duration
}
}

/// Max time before stop iterating
var timeout: DispatchTimeInterval{
switch self{
case .constant(_, _, let timeout) : return timeout
case .exponential(_, _, _, let timeout) : return timeout
var timeout: DispatchTimeInterval {
switch self {
case .constant(_, _, let timeout): return timeout
case .exponential(_, _, _, let timeout): return timeout
}
}
}
Expand Down
23 changes: 22 additions & 1 deletion Sources/retry-policy-service/ext/DispatchTimeInterval.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

import Foundation

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
import Foundation

// DispatchTimeInterval Extension for toDouble method
extension DispatchTimeInterval {

/// Convert to Double
Expand All @@ -29,3 +31,22 @@ extension DispatchTimeInterval {
}
}
}

extension DispatchTimeInterval {
func toDispatchTimeInterval() -> DispatchTimeInterval {
switch self {
case .seconds(let value):
return .seconds(value)
case .milliseconds(let value):
return .milliseconds(value)
case .microseconds(let value):
return .microseconds(value)
case .nanoseconds(let value):
return .nanoseconds(value)
case .never:
return .never
@unknown default:
return .never
}
}
}

0 comments on commit 2a6a1f0

Please sign in to comment.