Improve background uploading of PDFs

This commit is contained in:
Jackson Harper 2022-05-27 16:38:19 -07:00
parent 2918cbcdf5
commit 974757c7da
3 changed files with 71 additions and 28 deletions

View file

@ -26,6 +26,7 @@ final class ShareExtensionViewModel: ObservableObject {
@Published var debugText: String?
var subscriptions = Set<AnyCancellable>()
var backgroundTask: UIBackgroundTaskIdentifier?
let requestID = UUID().uuidString.lowercased()
init() {}
@ -41,11 +42,16 @@ final class ShareExtensionViewModel: ObservableObject {
}
func savePage(extensionContext: NSExtensionContext?) {
backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "BACKGROUND")
PageScraper.scrape(extensionContext: extensionContext) { [weak self] result in
switch result {
case let .success(payload):
self?.persist(pageScrapePayload: payload, requestId: self?.requestID ?? "")
case let .failure(error):
if let backgroundTask = self?.backgroundTask {
UIApplication.shared.endBackgroundTask(backgroundTask)
}
self?.debugText = error.message
}
}
@ -59,7 +65,6 @@ final class ShareExtensionViewModel: ObservableObject {
return
}
let backgroundTask = UIApplication.shared.beginBackgroundTask(withName: requestId)
let saveLinkPublisher: AnyPublisher<Void, SaveArticleError> = {
if case let .pdf(data) = pageScrapePayload.contentType {
return services.dataService.uploadPDFPublisher(pageScrapePayload: pageScrapePayload,
@ -80,10 +85,14 @@ final class ShareExtensionViewModel: ObservableObject {
guard case let .failure(error) = completion else { return }
self?.debugText = "saveArticleError: \(error)"
self?.status = .failed(error: error)
UIApplication.shared.endBackgroundTask(backgroundTask)
if let backgroundTask = self?.backgroundTask {
UIApplication.shared.endBackgroundTask(backgroundTask)
}
} receiveValue: { [weak self] _ in
self?.status = .success
UIApplication.shared.endBackgroundTask(backgroundTask)
if let backgroundTask = self?.backgroundTask {
UIApplication.shared.endBackgroundTask(backgroundTask)
}
}
.store(in: &subscriptions)

View file

@ -64,6 +64,7 @@ private extension DataService {
return Deferred {
Future { promise in
send(mutation, to: path, headers: headers) { result in
print("result of upload file request", result)
switch result {
case let .success(payload):
if let graphqlError = payload.errors {
@ -100,29 +101,43 @@ private extension DataService {
request.addValue("application/pdf", forHTTPHeaderField: "content-type")
request.httpBody = data
return networker.urlSession.dataTaskPublisher(for: request)
.tryMap { data, response -> String in
let serverResponse = ServerResponse(data: data, response: response)
if serverResponse.httpUrlResponse?.statusCode == 200, let fileUploadID = fileUploadConfig.uploadID {
return fileUploadID
}
// TODO: Maybe better to copy into this directory immediately
// instead of loading and writing the data
let tempDir = FileManager.default.temporaryDirectory
let localURL = tempDir.appendingPathComponent(fileUploadConfig.uploadFileID ?? "temporary")
try? data.write(to: localURL)
throw ServerError(serverResponse: serverResponse)
}
.mapError { error -> SaveArticleError in
let serverResponse = ServerResponse(error: error)
NetworkRequestLogger.log(request: request, serverResponse: serverResponse)
let serverError = ServerError(serverResponse: serverResponse)
switch serverError {
case .noConnection, .timeout:
return .network
case .unauthenticated:
return .unauthorized
case .unknown:
return .unknown(description: "upload to file server failed")
}
}
.eraseToAnyPublisher()
print("STARTING UPLOAD TASK WITH LOCAL URL", localURL)
let task = networker.backgroundSession.uploadTask(with: request, fromFile: localURL)
task.resume()
// Just return immediately at this point.
return Empty(completeImmediately: true).eraseToAnyPublisher()
// return "".publisher.eraseToAnyPublisher()
// return networker.urlSession.dataTaskPublisher(for: request)
// .tryMap { data, response -> String in
// let serverResponse = ServerResponse(data: data, response: response)
// if serverResponse.httpUrlResponse?.statusCode == 200, let fileUploadID = fileUploadConfig.uploadID {
// return fileUploadID
// }
//
// throw ServerError(serverResponse: serverResponse)
// }
// .mapError { error -> SaveArticleError in
// let serverResponse = ServerResponse(error: error)
// NetworkRequestLogger.log(request: request, serverResponse: serverResponse)
// let serverError = ServerError(serverResponse: serverResponse)
// switch serverError {
// case .noConnection, .timeout:
// return .network
// case .unauthenticated:
// return .unauthorized
// case .unknown:
// return .unknown(description: "upload to file server failed")
// }
// }
// .eraseToAnyPublisher()
}
// swiftlint:disable:next line_length

View file

@ -1,7 +1,7 @@
import Foundation
import Models
public final class Networker {
public final class Networker: NSObject, URLSessionTaskDelegate {
let urlSession: URLSession
let appEnvironment: AppEnvironment
@ -15,9 +15,28 @@ public final class Networker {
return headers
}
public init(appEnvironment: AppEnvironment, urlSession: URLSession = .shared) {
public init(appEnvironment: AppEnvironment) {
self.appEnvironment = appEnvironment
self.urlSession = urlSession
self.urlSession = .shared
}
lazy var backgroundSession: URLSession = {
let sessionConfig = URLSessionConfiguration.background(withIdentifier: "app.omnivoreapp.BackgroundSessionConfig")
sessionConfig.sharedContainerIdentifier = "group.app.omnivoreapp"
return URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
}()
public func urlSession(_: URLSession, task: URLSessionTask, didCompleteWithError _: Error?) {
print("finished upload of file:", task.taskIdentifier)
}
public func urlSession(_: URLSession,
task: URLSessionTask,
didSendBodyData _: Int64,
totalBytesSent: Int64,
totalBytesExpectedToSend _: Int64)
{
print("sent background data:", task.taskIdentifier, totalBytesSent)
}
}