Skip to content

Commit

Permalink
refactor(DownloadOperation): Split into subclasses (#1367)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrien-coye authored Dec 30, 2024
2 parents 8eedeca + 42a8b05 commit f3c9853
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,19 @@ public class DownloadOperation: Operation, DownloadOperationable {
// MARK: - Attributes

private let fileManager = FileManager.default
private let driveFileManager: DriveFileManager
private let urlSession: FileDownloadSession
private let publicShareProxy: PublicShareProxy?
private let itemIdentifier: NSFileProviderItemIdentifier?
private var progressObservation: NSKeyValueObservation?
private var backgroundTaskIdentifier: UIBackgroundTaskIdentifier = .invalid

@LazyInjectService(customTypeIdentifier: kDriveDBID.uploads) private var uploadsDatabase: Transactionable

@LazyInjectService(customTypeIdentifier: kDriveDBID.uploads) var uploadsDatabase: Transactionable
@LazyInjectService var accountManager: AccountManageable
@LazyInjectService var driveInfosManager: DriveInfosManager
@LazyInjectService var downloadManager: BackgroundDownloadSessionManager
@LazyInjectService var appContextService: AppContextServiceable

let urlSession: FileDownloadSession
let driveFileManager: DriveFileManager
var progressObservation: NSKeyValueObservation?

public let file: File
public var task: URLSessionDownloadTask?
public var error: DriveError?
Expand Down Expand Up @@ -94,13 +93,11 @@ public class DownloadOperation: Operation, DownloadOperationable {
file: File,
driveFileManager: DriveFileManager,
urlSession: FileDownloadSession,
publicShareProxy: PublicShareProxy? = nil,
itemIdentifier: NSFileProviderItemIdentifier? = nil
) {
self.file = File(value: file)
self.driveFileManager = driveFileManager
self.urlSession = urlSession
self.publicShareProxy = publicShareProxy
self.itemIdentifier = itemIdentifier
}

Expand All @@ -112,7 +109,6 @@ public class DownloadOperation: Operation, DownloadOperationable {
self.driveFileManager = driveFileManager
self.urlSession = urlSession
self.task = task
publicShareProxy = nil
itemIdentifier = nil
}

Expand Down Expand Up @@ -179,17 +175,13 @@ public class DownloadOperation: Operation, DownloadOperationable {
override public func main() {
DDLogInfo("[DownloadOperation] Start for \(file.id) with session \(urlSession.identifier)")

if let publicShareProxy {
downloadPublicShareFile(publicShareProxy: publicShareProxy)
} else {
downloadFile()
}
downloadFile()
}

private func downloadPublicShareFile(publicShareProxy: PublicShareProxy) {
DDLogInfo("[DownloadOperation] Downloading publicShare \(file.id) with session \(urlSession.identifier)")
private func downloadFile() {
DDLogInfo("[DownloadOperation] Downloading \(file.id) with session \(urlSession.identifier)")

let url = Endpoint.download(file: file, publicShareProxy: publicShareProxy).url
let url = Endpoint.download(file: file).url

// Add download task to Realm
let downloadTask = DownloadTask(
Expand All @@ -205,7 +197,17 @@ public class DownloadOperation: Operation, DownloadOperationable {
writableRealm.add(downloadTask, update: .modified)
}

let request = URLRequest(url: url)
if let token = getToken() {
var request = URLRequest(url: url)
request.setValue("Bearer \(token.accessToken)", forHTTPHeaderField: "Authorization")
downloadRequest(request)
} else {
error = .unknownToken // Other error?
end(sessionUrl: url)
}
}

func downloadRequest(_ request: URLRequest) {
task = urlSession.downloadTask(with: request, completionHandler: downloadCompletion)
progressObservation = task?.progress.observe(\.fractionCompleted, options: .new) { [fileId = file.id] _, value in
guard let newValue = value.newValue else {
Expand All @@ -223,49 +225,6 @@ public class DownloadOperation: Operation, DownloadOperationable {
task?.resume()
}

private func downloadFile() {
DDLogInfo("[DownloadOperation] Downloading \(file.id) with session \(urlSession.identifier)")

let url = Endpoint.download(file: file).url

// Add download task to Realm
let downloadTask = DownloadTask(
fileId: file.id,
isDirectory: file.isDirectory,
driveId: file.driveId,
userId: driveFileManager.drive.userId,
sessionId: urlSession.identifier,
sessionUrl: url.absoluteString
)

try? uploadsDatabase.writeTransaction { writableRealm in
writableRealm.add(downloadTask, update: .modified)
}

if let token = getToken() {
var request = URLRequest(url: url)
request.setValue("Bearer \(token.accessToken)", forHTTPHeaderField: "Authorization")
task = urlSession.downloadTask(with: request, completionHandler: downloadCompletion)
progressObservation = task?.progress.observe(\.fractionCompleted, options: .new) { [fileId = file.id] _, value in
guard let newValue = value.newValue else {
return
}
DownloadQueue.instance.publishProgress(newValue, for: fileId)
}
if let itemIdentifier {
driveInfosManager.getFileProviderManager(for: driveFileManager.drive) { manager in
manager.register(self.task!, forItemWithIdentifier: itemIdentifier) { _ in
// META: keep SonarCloud happy
}
}
}
task?.resume()
} else {
error = .unknownToken // Other error?
end(sessionUrl: url)
}
}

override public func cancel() {
DDLogInfo("[DownloadOperation] Download of \(file.id) canceled")
super.cancel()
Expand Down Expand Up @@ -342,7 +301,10 @@ public class DownloadOperation: Operation, DownloadOperationable {
return
}

assert(file.isDownloaded, "Expecting to be downloaded at the end of the downloadOperation error:\(error)")
assert(
file.isDownloaded,
"Expecting to be downloaded at the end of the downloadOperation error:\(String(describing: error))"
)

try? uploadsDatabase.writeTransaction { writableRealm in
guard let task = writableRealm.objects(DownloadTask.self)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
Infomaniak kDrive - iOS App
Copyright (C) 2024 Infomaniak Network SA

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import CocoaLumberjackSwift
import FileProvider
import Foundation
import InfomaniakCore
import InfomaniakCoreDB
import InfomaniakDI
import InfomaniakLogin

public final class DownloadPublicShareOperation: DownloadOperation {
private let publicShareProxy: PublicShareProxy

override public init(
file: File,
driveFileManager: DriveFileManager,
urlSession: FileDownloadSession,
itemIdentifier: NSFileProviderItemIdentifier? = nil
) {
fatalError("Unavailable")
}

public init(
file: File,
driveFileManager: DriveFileManager,
urlSession: FileDownloadSession,
publicShareProxy: PublicShareProxy,
itemIdentifier: NSFileProviderItemIdentifier? = nil
) {
self.publicShareProxy = publicShareProxy
super.init(file: file,
driveFileManager: driveFileManager,
urlSession: urlSession,
itemIdentifier: itemIdentifier)
}

override public func main() {
DDLogInfo("[DownloadPublicShareOperation] Start for \(file.id) with session \(urlSession.identifier)")

downloadPublicShareFile(publicShareProxy: publicShareProxy)
}

private func downloadPublicShareFile(publicShareProxy: PublicShareProxy) {
DDLogInfo("[DownloadPublicShareOperation] Downloading publicShare \(file.id) with session \(urlSession.identifier)")

let url = Endpoint.download(file: file, publicShareProxy: publicShareProxy).url

// Add download task to Realm
let downloadTask = DownloadTask(
fileId: file.id,
isDirectory: file.isDirectory,
driveId: file.driveId,
userId: driveFileManager.drive.userId,
sessionId: urlSession.identifier,
sessionUrl: url.absoluteString
)

try? uploadsDatabase.writeTransaction { writableRealm in
writableRealm.add(downloadTask, update: .modified)
}

let request = URLRequest(url: url)
downloadRequest(request)
}
}
2 changes: 1 addition & 1 deletion kDriveCore/Data/DownloadQueue/DownloadQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public final class DownloadQueue: ParallelismHeuristicDelegate {

OperationQueueHelper.disableIdleTimer(true)

let operation = DownloadOperation(
let operation = DownloadPublicShareOperation(
file: file,
driveFileManager: driveFileManager,
urlSession: self.bestSession,
Expand Down

0 comments on commit f3c9853

Please sign in to comment.