mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-18 16:49:10 +02:00
Somewhat working progress under heavy load
This commit is contained in:
parent
ad802c16ea
commit
b1b10e846d
2 changed files with 42 additions and 16 deletions
|
@ -16,6 +16,10 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
private let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
private let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||||
private lazy var session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue.main)
|
private lazy var session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue.main)
|
||||||
|
|
||||||
|
private let progressStatusQueue = DispatchQueue(label: "progress-status")
|
||||||
|
private var progressStatusWorkItem: DispatchWorkItem?
|
||||||
|
private var downloadItemQueue = [String: DownloadItem]()
|
||||||
|
|
||||||
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
||||||
handleDownloadTaskUpdate(downloadTask: downloadTask) { downloadItem, downloadItemPart in
|
handleDownloadTaskUpdate(downloadTask: downloadTask) { downloadItem, downloadItemPart in
|
||||||
downloadItemPart.progress = 1
|
downloadItemPart.progress = 1
|
||||||
|
@ -61,29 +65,29 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
|
|
||||||
// Find the download item
|
// Find the download item
|
||||||
let downloadItem = Database.shared.getDownloadItem(downloadItemPartId: downloadItemPartId)
|
let downloadItem = Database.shared.getDownloadItem(downloadItemPartId: downloadItemPartId)
|
||||||
guard let downloadItem = downloadItem else { throw LibraryItemDownloadError.downloadItemNotFound }
|
guard var downloadItem = downloadItem else { throw LibraryItemDownloadError.downloadItemNotFound }
|
||||||
|
downloadItem = self.downloadItemQueue[downloadItem.id!] ?? downloadItem
|
||||||
|
|
||||||
// Find the download item part
|
// Find the download item part
|
||||||
let downloadItemPart = downloadItem.downloadItemParts.filter { $0.id == downloadItemPartId }.first
|
let partIndex = downloadItem.downloadItemParts.firstIndex(where: { $0.id == downloadItemPartId })
|
||||||
guard var downloadItemPart = downloadItemPart else { throw LibraryItemDownloadError.downloadItemPartNotFound }
|
guard let partIndex = partIndex else { throw LibraryItemDownloadError.downloadItemPartNotFound }
|
||||||
|
|
||||||
// Call the progress handler
|
// Call the progress handler
|
||||||
do {
|
do {
|
||||||
try progressHandler(downloadItem, &downloadItemPart)
|
try progressHandler(downloadItem, &downloadItem.downloadItemParts[partIndex])
|
||||||
} catch {
|
} catch {
|
||||||
NSLog("Error while processing progress")
|
NSLog("Error while processing progress")
|
||||||
debugPrint(error)
|
debugPrint(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the progress
|
// Update the progress
|
||||||
Database.shared.updateDownloadItemPart(downloadItemPart)
|
self.downloadItemQueue.updateValue(downloadItem, forKey: downloadItem.id!)
|
||||||
|
|
||||||
// Notify the UI
|
// Notify the UI
|
||||||
try? notifyListeners("onItemDownloadUpdate", data: downloadItem.asDictionary())
|
self.notifyDownloadProgress()
|
||||||
|
|
||||||
// Handle a completed download
|
// Handle a completed download
|
||||||
if ( downloadItem.isDoneDownloading() ) {
|
if ( downloadItem.isDoneDownloading() ) {
|
||||||
// Delete the download item on exit even if handling complete errors
|
|
||||||
defer { Database.shared.removeDownloadItem(downloadItem) }
|
defer { Database.shared.removeDownloadItem(downloadItem) }
|
||||||
handleDownloadTaskCompleteFromDownloadItem(downloadItem)
|
handleDownloadTaskCompleteFromDownloadItem(downloadItem)
|
||||||
}
|
}
|
||||||
|
@ -93,6 +97,35 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We want to handle updating the UI in the background and throttled so we don't overload the UI with progress updates
|
||||||
|
private func notifyDownloadProgress() {
|
||||||
|
// Return if the loop is running
|
||||||
|
guard self.progressStatusWorkItem == nil else { return }
|
||||||
|
|
||||||
|
// Create a background thread to send the download status
|
||||||
|
self.progressStatusWorkItem = DispatchWorkItem { [weak self] in // Weak capture so the bg thread is pulling latest data
|
||||||
|
// Clean up the work item when done
|
||||||
|
defer { self?.progressStatusWorkItem = nil }
|
||||||
|
|
||||||
|
while !(self?.downloadItemQueue.isEmpty ?? true) {
|
||||||
|
for item in self!.downloadItemQueue.values {
|
||||||
|
try? self!.notifyListeners("onItemDownloadUpdate", data: item.asDictionary())
|
||||||
|
|
||||||
|
// Clean up a completed download
|
||||||
|
if item.isDoneDownloading() {
|
||||||
|
self!.downloadItemQueue.removeValue(forKey: item.id!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait 200ms before reporting status again
|
||||||
|
Thread.sleep(forTimeInterval: TimeInterval(0.2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the thread
|
||||||
|
self.progressStatusQueue.async(execute: self.progressStatusWorkItem!)
|
||||||
|
}
|
||||||
|
|
||||||
private func handleDownloadTaskCompleteFromDownloadItem(_ downloadItem: DownloadItem) {
|
private func handleDownloadTaskCompleteFromDownloadItem(_ downloadItem: DownloadItem) {
|
||||||
if ( downloadItem.didDownloadSuccessfully() ) {
|
if ( downloadItem.didDownloadSuccessfully() ) {
|
||||||
|
|
||||||
|
@ -145,13 +178,6 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
NSLog("Download library item \(libraryItemId ?? "N/A") / episode \(episodeId ?? "N/A")")
|
NSLog("Download library item \(libraryItemId ?? "N/A") / episode \(episodeId ?? "N/A")")
|
||||||
guard let libraryItemId = libraryItemId else { return call.resolve(["error": "libraryItemId not specified"]) }
|
guard let libraryItemId = libraryItemId else { return call.resolve(["error": "libraryItemId not specified"]) }
|
||||||
|
|
||||||
// Verify the file isn't already downloading
|
|
||||||
let downloadItemId = episodeId != nil ? "\(libraryItemId)-\(episodeId!)" : libraryItemId
|
|
||||||
let downloadItem = Database.shared.getDownloadItem(downloadItemId: downloadItemId)
|
|
||||||
if ( downloadItem != nil ) {
|
|
||||||
return call.resolve(["error": "Download already started for this media entity"])
|
|
||||||
}
|
|
||||||
|
|
||||||
ApiClient.getLibraryItemWithProgress(libraryItemId: libraryItemId, episodeId: episodeId) { libraryItem in
|
ApiClient.getLibraryItemWithProgress(libraryItemId: libraryItemId, episodeId: episodeId) { libraryItem in
|
||||||
if let libraryItem = libraryItem {
|
if let libraryItem = libraryItem {
|
||||||
NSLog("Got library item from server \(libraryItem.id)")
|
NSLog("Got library item from server \(libraryItem.id)")
|
||||||
|
|
|
@ -120,7 +120,7 @@ class Database {
|
||||||
|
|
||||||
public func saveLocalLibraryItem(localLibraryItem: LocalLibraryItem) {
|
public func saveLocalLibraryItem(localLibraryItem: LocalLibraryItem) {
|
||||||
let realm = try! Realm()
|
let realm = try! Realm()
|
||||||
try! realm.write { realm.add(localLibraryItem) }
|
try! realm.write { realm.add(localLibraryItem, update: .modified) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getDownloadItem(downloadItemId: String) -> DownloadItem? {
|
public func getDownloadItem(downloadItemId: String) -> DownloadItem? {
|
||||||
|
@ -140,7 +140,7 @@ class Database {
|
||||||
|
|
||||||
public func saveDownloadItem(_ downloadItem: DownloadItem) {
|
public func saveDownloadItem(_ downloadItem: DownloadItem) {
|
||||||
let realm = try! Realm()
|
let realm = try! Realm()
|
||||||
return try! realm.write { realm.add(downloadItem) }
|
return try! realm.write { realm.add(downloadItem, update: .modified) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateDownloadItemPart(_ part: DownloadItemPart) {
|
public func updateDownloadItemPart(_ part: DownloadItemPart) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue