codeburn/mac/Sources/CodeBurnMenubar/RefreshBackoff.swift

47 lines
1.4 KiB
Swift

import Foundation
struct RefreshBackoff {
let stallThreshold: Int
let initialDelay: TimeInterval
let maximumDelay: TimeInterval
private(set) var consecutiveStalls = 0
private(set) var pausedUntil: Date?
init(stallThreshold: Int = 3, initialDelay: TimeInterval = 30, maximumDelay: TimeInterval = 300) {
self.stallThreshold = stallThreshold
self.initialDelay = initialDelay
self.maximumDelay = maximumDelay
}
mutating func recordStall(now: Date = Date()) -> Date? {
consecutiveStalls += 1
guard consecutiveStalls >= stallThreshold else { return nil }
let exponent = max(0, consecutiveStalls - stallThreshold)
let multiplier = pow(2.0, Double(exponent))
let delay = min(initialDelay * multiplier, maximumDelay)
let until = now.addingTimeInterval(delay)
pausedUntil = until
return until
}
mutating func recordSuccess() {
consecutiveStalls = 0
pausedUntil = nil
}
mutating func retryNow(resetStallCount: Bool = false) {
pausedUntil = nil
if resetStallCount {
consecutiveStalls = 0
}
}
mutating func isPaused(now: Date = Date()) -> Bool {
guard let pausedUntil else { return false }
if pausedUntil > now { return true }
self.pausedUntil = nil
return false
}
}