Refactor task usage and profile auto update
This commit is contained in:
@@ -2,44 +2,59 @@ 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 setup() throws {
|
||||
var earliestBeginDate: Date?
|
||||
if let updatedAt = try oldestUpdated() {
|
||||
if updatedAt > Date(timeIntervalSinceNow: -taskInterval) {
|
||||
earliestBeginDate = updatedAt.addingTimeInterval(taskInterval)
|
||||
}
|
||||
public static func configure() async throws {
|
||||
timer?.invalidate()
|
||||
timer = nil
|
||||
let profiles = try await ProfileManager.listAutoUpdateEnabled()
|
||||
if profiles.isEmpty {
|
||||
return
|
||||
}
|
||||
timer = Timer(fire: earliestBeginDate ?? Date.now, interval: taskInterval, repeats: true, block: { _ in
|
||||
do {
|
||||
_ = try updateProfiles()
|
||||
NSLog("profile update task succeed")
|
||||
} catch {
|
||||
NSLog("profile update task failed: \(error.localizedDescription)")
|
||||
var updateInterval = profiles.map { it in
|
||||
it.autoUpdateIntervalOrDefault
|
||||
}.min()!
|
||||
if updateInterval < minUpdateInterval {
|
||||
updateInterval = minUpdateInterval
|
||||
}
|
||||
timer = Timer(fire: calculateEarliestBeginDate(profiles), interval: updateInterval, repeats: true, block: { _ in
|
||||
Task {
|
||||
await getAndupdateProfiles()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static let taskInterval: TimeInterval = 15 * 60
|
||||
|
||||
static func oldestUpdated() throws -> Date? {
|
||||
let profiles = try ProfileManager.listAutoUpdateEnabled()
|
||||
return profiles.map { profile in
|
||||
profile.lastUpdated!
|
||||
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
|
||||
}
|
||||
.min()
|
||||
return earliestBeginDate
|
||||
}
|
||||
|
||||
static func updateProfiles() throws -> Bool {
|
||||
let profiles = try ProfileManager.listAutoUpdateEnabled()
|
||||
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 throws -> Bool {
|
||||
var success = true
|
||||
for profile in profiles {
|
||||
if profile.lastUpdated! > Date(timeIntervalSinceNow: -taskInterval) {
|
||||
if profile.lastUpdated! > Date(timeIntervalSinceNow: -profile.autoUpdateIntervalOrDefault) {
|
||||
continue
|
||||
}
|
||||
do {
|
||||
try profile.updateRemoteProfile()
|
||||
try await profile.updateRemoteProfile()
|
||||
} catch {
|
||||
NSLog("Update profile \(profile.name) failed: \(error.localizedDescription)")
|
||||
success = false
|
||||
@@ -48,3 +63,13 @@ public enum ProfileUpdateTask {
|
||||
return success
|
||||
}
|
||||
}
|
||||
|
||||
extension Profile {
|
||||
var autoUpdateIntervalOrDefault: TimeInterval {
|
||||
if autoUpdateInterval > 0 {
|
||||
return TimeInterval(autoUpdateInterval * 60)
|
||||
} else {
|
||||
return ProfileUpdateTask.defaultUpdateInterval
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,37 +4,49 @@ import Library
|
||||
|
||||
#if os(iOS) || os(tvOS)
|
||||
public class UIProfileUpdateTask: BGAppRefreshTask {
|
||||
public static let taskSchedulerPermittedIdentifier = "\(FilePath.packageName).update_profiles"
|
||||
private static let taskSchedulerPermittedIdentifier = "\(FilePath.packageName).update_profiles"
|
||||
|
||||
public static func setup() async throws {
|
||||
public static func configure() async throws {
|
||||
let success = BGTaskScheduler.shared.register(forTaskWithIdentifier: taskSchedulerPermittedIdentifier, using: nil) { task in
|
||||
NSLog("profile update task started")
|
||||
do {
|
||||
let success = try ProfileUpdateTask.updateProfiles()
|
||||
try? scheduleUpdate(Date(timeIntervalSinceNow: ProfileUpdateTask.taskInterval))
|
||||
task.setTaskCompleted(success: success)
|
||||
NSLog("profile update task succeed")
|
||||
} catch {
|
||||
try? scheduleUpdate(nil)
|
||||
task.setTaskCompleted(success: false)
|
||||
NSLog("profile update task failed: \(error.localizedDescription)")
|
||||
}
|
||||
task.expirationHandler = {
|
||||
try? scheduleUpdate(nil)
|
||||
NSLog("profile update task expired")
|
||||
Task {
|
||||
await getAndupdateProfiles(task)
|
||||
}
|
||||
}
|
||||
if !success {
|
||||
throw NSError(domain: "register failed", code: 0)
|
||||
}
|
||||
if await BGTaskScheduler.shared.pendingTaskRequests().isEmpty {
|
||||
var earliestBeginDate: Date? = nil
|
||||
if let updatedAt = try ProfileUpdateTask.oldestUpdated() {
|
||||
if updatedAt > Date(timeIntervalSinceNow: -ProfileUpdateTask.taskInterval) {
|
||||
earliestBeginDate = updatedAt.addingTimeInterval(ProfileUpdateTask.taskInterval)
|
||||
}
|
||||
}
|
||||
try scheduleUpdate(earliestBeginDate)
|
||||
BGTaskScheduler.shared.cancelAllTaskRequests()
|
||||
let profiles = try await ProfileManager.listAutoUpdateEnabled()
|
||||
if profiles.isEmpty {
|
||||
return
|
||||
}
|
||||
try scheduleUpdate(ProfileUpdateTask.calculateEarliestBeginDate(profiles))
|
||||
}
|
||||
|
||||
private nonisolated static func getAndupdateProfiles(_ task: BGTask) async {
|
||||
let profiles: [Profile]
|
||||
do {
|
||||
profiles = try await ProfileManager.listAutoUpdateEnabled()
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
if profiles.isEmpty {
|
||||
return
|
||||
}
|
||||
do {
|
||||
let success = try await ProfileUpdateTask.updateProfiles(profiles)
|
||||
try? scheduleUpdate(ProfileUpdateTask.calculateEarliestBeginDate(profiles))
|
||||
task.setTaskCompleted(success: success)
|
||||
NSLog("profile update task succeed")
|
||||
} catch {
|
||||
try? scheduleUpdate(nil)
|
||||
task.setTaskCompleted(success: false)
|
||||
NSLog("profile update task failed: \(error.localizedDescription)")
|
||||
}
|
||||
task.expirationHandler = {
|
||||
try? scheduleUpdate(nil)
|
||||
NSLog("profile update task expired")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user