Call uploadFileRequest before uploading files

App Engine cant handle larger request sizes, so using a redirect
here doesn't work.
This commit is contained in:
Jackson Harper
2022-05-31 15:11:51 -07:00
parent 0e10d5630d
commit cbf0215936
4 changed files with 107 additions and 105 deletions

View File

@ -67,9 +67,10 @@ final class ShareExtensionViewModel: ObservableObject {
let linkedItem = try? await services.dataService.persistPageScrapePayload(pageScrapePayload, requestId: requestId)
if let linkedItem = linkedItem {
// Sync with server now that we saved the item locally
services.dataService.syncLocalCreatedLinkedItem(item: linkedItem)
updateStatus(newStatus: .saved)
await services.dataService.syncLocalCreatedLinkedItem(item: linkedItem)
updateStatus(newStatus: .synced)
} else {
updateStatus(newStatus: .failed(error: SaveArticleError.unknown(description: "Unable to save page")))
}

View File

@ -26,9 +26,7 @@ private struct UploadFileRequestPayload {
}
private extension DataService {
// swiftlint:disable:next line_length
// func uploadFileRequestPublisher(pageScrapePayload: PageScrapePayload, requestId: String?) -> AnyPublisher<UploadFileRequestPayload, SaveArticleError> {
func uploadFileRequestPublisher(item: LinkedItem) -> AnyPublisher<UploadFileRequestPayload, SaveArticleError> {
public func uploadFileRequest(item: LinkedItem) async throws -> URL {
enum MutationResult {
case success(payload: UploadFileRequestPayload)
case error(errorCode: Enums.UploadFileRequestErrorCode?)
@ -63,84 +61,51 @@ private extension DataService {
let path = appEnvironment.graphqlPath
let headers = networker.defaultHeaders
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 {
promise(.failure(.unknown(description: graphqlError.first.debugDescription)))
}
switch payload.data {
case let .success(payload):
promise(.success(payload))
case let .error(errorCode):
switch errorCode {
case .unauthorized:
promise(.failure(.unauthorized))
default:
promise(.failure(.unknown(description: errorCode.debugDescription)))
}
}
case .failure:
promise(.failure(.badData))
return try await withCheckedThrowingContinuation { continuation in
send(mutation, to: path, headers: headers) { result in
switch result {
case let .success(payload):
if let graphqlError = payload.errors {
continuation.resume(
throwing: SaveArticleError.unknown(description: graphqlError.first.debugDescription)
)
return
}
switch payload.data {
case let .success(payload):
if let urlString = payload.urlString, let url = URL(string: urlString) {
continuation.resume(returning: url)
} else {
continuation.resume(throwing: SaveArticleError.unknown(description: "No upload URL"))
}
case let .error(errorCode: errorCode):
switch errorCode {
case .unauthorized:
continuation.resume(throwing: SaveArticleError.unauthorized)
default:
continuation.resume(throwing: SaveArticleError.unknown(description: errorCode?.rawValue ?? "unknown"))
}
}
case let .failure(error):
continuation.resume(throwing: SaveArticleError.make(from: error))
}
}
}
.eraseToAnyPublisher()
}
// swiftlint:disable:next line_length
public func uploadFilePublisher(item: LinkedItem) -> AnyPublisher<String, SaveArticleError> {
var urlComponents = URLComponents(url: appEnvironment.serverBaseURL, resolvingAgainstBaseURL: true)!
// let headers = networker.defaultHeaders
urlComponents.path = "/api/page/pdf"
urlComponents.queryItems = [URLQueryItem(name: "url", value: item.pageURLString), URLQueryItem(name: "clientRequestId", value: item.unwrappedID)]
public func uploadFile(item: LinkedItem, url: URL) -> URLSessionTask? {
if let localPdfURL = item.localPdfURL, let localUrl = URL(string: localPdfURL) {
print("UPLOADING TO URL", urlComponents.url)
var request = URLRequest(url: urlComponents.url!)
var request = URLRequest(url: url)
request.httpMethod = "PUT"
networker.defaultHeaders.forEach { (key: String, value: String) in
request.addValue(value, forHTTPHeaderField: key)
}
request.setValue("application/pdf", forHTTPHeaderField: "content-type")
let task = networker.backgroundSession.uploadTask(with: request, fromFile: localUrl)
task.resume()
return task
} else {
return nil
}
// 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

@ -35,40 +35,38 @@ extension DataService {
}
}
public func syncLocalCreatedLinkedItem(item: LinkedItem) {
public func syncLocalCreatedLinkedItem(item: LinkedItem) async -> Bool {
switch item.contentReader {
case "PDF":
// SaveFile
uploadFilePublisher(item: item)
.sink(receiveCompletion: { [weak self] _ in
print("received PDF saved completion")
}, receiveValue: { [weak self] _ in
print("recived save PDF value", item)
})
.store(in: &subscriptions)
case "WEB":
if item.originalHtml != nil {
savePagePublisher(item: item)
.sink(receiveCompletion: { [weak self] _ in
print("received page saved completion")
}, receiveValue: { [weak self] _ in
print("recived save page value", item)
})
.store(in: &subscriptions)
} else {
saveUrlPublisher(item: item)
.sink(receiveCompletion: { [weak self] _ in
print("received url saved completion")
}, receiveValue: { [weak self] _ in
// print("recived save url value", item)
})
.store(in: &subscriptions)
do {
let uploadRequest = try await uploadFileRequest(item: item)
uploadFile(item: item, url: uploadRequest)
} catch {
logger.debug("Failed to upload PDF LinkedItem: \(error.localizedDescription)")
return false
}
case .none:
print("NONE HANDLER")
case .some:
print("SOME HANDLER")
case "WEB":
do {
if item.originalHtml != nil {
try await savePage(item: item)
} else {
try await saveURL(item: item)
}
item.serverSyncStatus = Int64(ServerSyncStatus.isNSync.rawValue)
print("ITEMS SYNCED")
try backgroundContext.save()
return true
} catch {
print("Error saving", error)
backgroundContext.rollback()
logger.debug("Failed to sync LinkedItem: \(error.localizedDescription)")
return false
}
default:
return false
}
return false
}
private func syncLinkedItems(unsyncedLinkedItems: [LinkedItem]) {
@ -77,7 +75,8 @@ extension DataService {
switch syncStatus {
case .needsCreation:
syncLocalCreatedLinkedItem(item: item)
// syncLocalCreatedLinkedItem(item: item)
break
case .isNSync, .isSyncing:
break
case .needsDeletion:

View File

@ -143,7 +143,20 @@ public struct ShareExtensionChildView: View {
Spacer()
if case ShareExtensionStatus.saved = status {
switch status {
case .processing:
HStack {
Spacer()
Text("Saving...")
Spacer()
}
case .saved:
HStack {
Spacer()
Text("Syncing...")
Spacer()
}
case .synced:
HStack(spacing: 4) {
Text("Saved to Omnivore")
.font(.appTitleThree)
@ -154,19 +167,43 @@ public struct ShareExtensionChildView: View {
.lineLimit(nil)
}
.padding()
} else if case let ShareExtensionStatus.failed(error) = status {
case let .failed(error: error):
HStack {
Spacer()
Text(error.displayMessage)
Text("Failed to save:" + error.displayMessage)
Spacer()
}
} else {
case let .syncFailed(error: error):
HStack {
Spacer()
Text("Saving...")
Text("Failed to sync:" + error.displayMessage)
Spacer()
}
}
// if case ShareExtensionStatus.saved = status {
// HStack(spacing: 4) {
// Text("Saved to Omnivore")
// .font(.appTitleThree)
// .foregroundColor(.appGrayText)
// .padding(.trailing, 16)
// .multilineTextAlignment(.center)
// .fixedSize(horizontal: false, vertical: true)
// .lineLimit(nil)
// }
// .padding()
// } else if case let ShareExtensionStatus.failed(error) = status {
// HStack {
// Spacer()
// Text(error.displayMessage)
// Spacer()
// }
// } else {
// HStack {
// Spacer()
// Text("Saving...")
// Spacer()
// }
// }
ScrollView {
if FeatureFlag.enableRemindersFromShareExtension {