mirror of
https://github.com/SagerNet/sing-box-for-apple.git
synced 2026-05-04 11:32:29 +00:00
5318c1b84c
Snapshot @Published properties before async suspension points to prevent SIGBUS from corrupted pointers due to concurrent access.
80 lines
2.5 KiB
Swift
80 lines
2.5 KiB
Swift
import Foundation
|
|
import Library
|
|
|
|
public enum ProfileUpdateTask {
|
|
static let minUpdateInterval: TimeInterval = 15 * 60
|
|
static let defaultUpdateInterval: TimeInterval = 60 * 60
|
|
|
|
private static var timer: Timer?
|
|
|
|
public static func configure() async throws {
|
|
timer?.invalidate()
|
|
timer = nil
|
|
let profiles = try await ProfileManager.listAutoUpdateEnabled()
|
|
if profiles.isEmpty {
|
|
return
|
|
}
|
|
var updateInterval = profiles.map { it in
|
|
it.autoUpdateIntervalOrDefault
|
|
}.min()!
|
|
if updateInterval < minUpdateInterval {
|
|
updateInterval = minUpdateInterval
|
|
}
|
|
let newTimer = Timer(fire: calculateEarliestBeginDate(profiles), interval: updateInterval, repeats: true) { _ in
|
|
Task {
|
|
await getAndupdateProfiles()
|
|
}
|
|
}
|
|
RunLoop.main.add(newTimer, forMode: .common)
|
|
timer = newTimer
|
|
}
|
|
|
|
static func calculateEarliestBeginDate(_ profiles: [Profile]) -> Date {
|
|
let nowTime = Date.now
|
|
var earliestBeginDate = profiles.map { it in
|
|
it.lastUpdated!.addingTimeInterval(it.autoUpdateIntervalOrDefault)
|
|
}.min()!
|
|
if earliestBeginDate <= nowTime {
|
|
earliestBeginDate = nowTime
|
|
}
|
|
return earliestBeginDate
|
|
}
|
|
|
|
private nonisolated static func getAndupdateProfiles() async {
|
|
do {
|
|
_ = try await updateProfiles(ProfileManager.listAutoUpdateEnabled())
|
|
NSLog("profile update task succeed")
|
|
} catch {
|
|
NSLog("profile update task failed: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
static func updateProfiles(_ profiles: [Profile]) async -> Bool {
|
|
var success = true
|
|
for profile in profiles {
|
|
let profileName = profile.name
|
|
if profile.lastUpdated! > Date(timeIntervalSinceNow: -profile.autoUpdateIntervalOrDefault) {
|
|
continue
|
|
}
|
|
do {
|
|
try await profile.updateRemoteProfile()
|
|
NSLog("Updated profile %@", profileName)
|
|
} catch {
|
|
NSLog("Update profile %@ failed: %@", profileName, error.localizedDescription)
|
|
success = false
|
|
}
|
|
}
|
|
return success
|
|
}
|
|
}
|
|
|
|
extension Profile {
|
|
var autoUpdateIntervalOrDefault: TimeInterval {
|
|
if autoUpdateInterval > 0 {
|
|
return TimeInterval(autoUpdateInterval * 60)
|
|
} else {
|
|
return ProfileUpdateTask.defaultUpdateInterval
|
|
}
|
|
}
|
|
}
|