mirror of
https://github.com/immich-app/immich.git
synced 2026-03-23 04:39:10 +03:00
add schemas sync variants formatting initial implementation use existing db, wip move to separate folder fix table definitions wip wiring it up repository pattern
128 lines
4.6 KiB
Swift
128 lines
4.6 KiB
Swift
import BackgroundTasks
|
|
|
|
class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
|
|
|
func enable() throws {
|
|
BackgroundWorkerApiImpl.scheduleRefreshWorker()
|
|
BackgroundWorkerApiImpl.scheduleProcessingWorker()
|
|
print("BackgroundWorkerApiImpl:enable Background worker scheduled")
|
|
}
|
|
|
|
func configure(settings: BackgroundWorkerSettings) throws {
|
|
// Android only
|
|
}
|
|
|
|
func saveNotificationMessage(title: String, body: String) throws {
|
|
// Android only
|
|
}
|
|
|
|
func disable() throws {
|
|
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.refreshTaskID);
|
|
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.processingTaskID);
|
|
print("BackgroundWorkerApiImpl:disableUploadWorker Disabled background workers")
|
|
}
|
|
|
|
private static let refreshTaskID = "app.alextran.immich.background.refreshUpload"
|
|
private static let processingTaskID = "app.alextran.immich.background.processingUpload"
|
|
private static let taskSemaphore = DispatchSemaphore(value: 1)
|
|
|
|
public static func registerBackgroundWorkers() {
|
|
BGTaskScheduler.shared.register(
|
|
forTaskWithIdentifier: processingTaskID, using: nil) { task in
|
|
if case let task as BGProcessingTask = task {
|
|
handleBackgroundProcessing(task: task)
|
|
}
|
|
}
|
|
|
|
BGTaskScheduler.shared.register(
|
|
forTaskWithIdentifier: refreshTaskID, using: nil) { task in
|
|
if case let task as BGAppRefreshTask = task {
|
|
handleBackgroundRefresh(task: task)
|
|
}
|
|
}
|
|
}
|
|
|
|
private static func scheduleRefreshWorker() {
|
|
let backgroundRefresh = BGAppRefreshTaskRequest(identifier: refreshTaskID)
|
|
backgroundRefresh.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60) // 5 mins
|
|
|
|
do {
|
|
try BGTaskScheduler.shared.submit(backgroundRefresh)
|
|
} catch {
|
|
print("Could not schedule the refresh upload task \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
private static func scheduleProcessingWorker() {
|
|
let backgroundProcessing = BGProcessingTaskRequest(identifier: processingTaskID)
|
|
|
|
backgroundProcessing.requiresNetworkConnectivity = true
|
|
backgroundProcessing.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 mins
|
|
|
|
do {
|
|
try BGTaskScheduler.shared.submit(backgroundProcessing)
|
|
} catch {
|
|
print("Could not schedule the processing upload task \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
private static func handleBackgroundRefresh(task: BGAppRefreshTask) {
|
|
scheduleRefreshWorker()
|
|
// If another task is running, cede the background time back to the OS
|
|
if taskSemaphore.wait(timeout: .now()) == .success {
|
|
// Restrict the refresh task to run only for a maximum of (maxSeconds) seconds
|
|
runBackgroundWorker(task: task, taskType: .refresh, maxSeconds: 20)
|
|
} else {
|
|
task.setTaskCompleted(success: false)
|
|
}
|
|
}
|
|
|
|
private static func handleBackgroundProcessing(task: BGProcessingTask) {
|
|
scheduleProcessingWorker()
|
|
taskSemaphore.wait()
|
|
// There are no restrictions for processing tasks. Although, the OS could signal expiration at any time
|
|
runBackgroundWorker(task: task, taskType: .processing, maxSeconds: nil)
|
|
}
|
|
|
|
/**
|
|
* Executes the background worker within the context of a background task.
|
|
* This method creates a BackgroundWorker, sets up task expiration handling,
|
|
* and manages the synchronization between the background task and the Flutter engine.
|
|
*
|
|
* - Parameters:
|
|
* - task: The iOS background task that provides the execution context
|
|
* - taskType: The type of background operation to perform (refresh or processing)
|
|
* - maxSeconds: Optional timeout for the operation in seconds
|
|
*/
|
|
private static func runBackgroundWorker(task: BGTask, taskType: BackgroundTaskType, maxSeconds: Int?) {
|
|
defer { taskSemaphore.signal() }
|
|
let semaphore = DispatchSemaphore(value: 0)
|
|
var isSuccess = true
|
|
|
|
let backgroundWorker = BackgroundWorker(taskType: taskType, maxSeconds: maxSeconds) { success in
|
|
isSuccess = success
|
|
semaphore.signal()
|
|
}
|
|
|
|
task.expirationHandler = {
|
|
DispatchQueue.main.async {
|
|
backgroundWorker.close()
|
|
}
|
|
isSuccess = false
|
|
|
|
// Schedule a timer to signal the semaphore after 2 seconds
|
|
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
|
|
semaphore.signal()
|
|
}
|
|
}
|
|
|
|
DispatchQueue.main.async {
|
|
backgroundWorker.run()
|
|
}
|
|
|
|
semaphore.wait()
|
|
task.setTaskCompleted(success: isSuccess)
|
|
print("Background task completed with success: \(isSuccess)")
|
|
}
|
|
}
|