Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(DownloadOperation): Split into subclasses #1367

Merged
merged 3 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading