Files
steipete--codexbar/Sources/CodexBar/UsageStore+StartupConnectivityRetry.swift
2026-07-13 12:22:33 +08:00

86 lines
2.8 KiB
Swift

import Foundation
extension UsageStore {
enum StartupBehavior {
case automatic
case full
case testing
var automaticallyStartsBackgroundWork: Bool {
switch self {
case .automatic, .full:
true
case .testing:
false
}
}
func resolved(isRunningTests: Bool) -> StartupBehavior {
switch self {
case .automatic:
isRunningTests ? .testing : .full
case .full, .testing:
self
}
}
}
func recordStartupConnectivityRetryableFailure(_ error: Error) {
guard self.startupConnectivityRetryRefreshActive else { return }
guard Self.isStartupConnectivityRetryableError(error) else { return }
self.startupConnectivityRetryNeeded = true
}
func completeStartupConnectivityRetryPass(currentAttempt: Int) {
guard self.startupConnectivityRetryNeeded else {
self.cancelStartupConnectivityRetry()
return
}
let nextAttempt = currentAttempt + 1
guard let delay = Self.startupConnectivityRetryDelay(forAttempt: nextAttempt) else {
self.cancelStartupConnectivityRetry()
return
}
self.scheduleStartupConnectivityRetry(attempt: nextAttempt, delay: delay)
}
private func scheduleStartupConnectivityRetry(attempt: Int, delay: TimeInterval) {
guard self.startupBehavior.automaticallyStartsBackgroundWork ||
self._test_startupConnectivityRetryScheduled != nil ||
self._test_startupConnectivityRetrySleepOverride != nil
else {
return
}
self.startupConnectivityRetryTask?.cancel()
self._test_startupConnectivityRetryScheduled?(attempt, delay)
self.startupConnectivityRetryTask = Task { @MainActor [weak self] in
guard let self else { return }
do {
try await self.sleepForStartupConnectivityRetry(delay)
guard !Task.isCancelled else { return }
await self.runRefresh(
startupConnectivityRetryAttempt: attempt,
waitForRefreshAvailability: true)
} catch {
return
}
}
}
private func cancelStartupConnectivityRetry() {
self.startupConnectivityRetryTask?.cancel()
self.startupConnectivityRetryTask = nil
}
private func sleepForStartupConnectivityRetry(_ delay: TimeInterval) async throws {
if let override = self._test_startupConnectivityRetrySleepOverride {
try await override(delay)
return
}
try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
}
}