field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

TeraStoppedUploadRecovery.swift (2259B)


      1 import Foundation
      2 import RadrootsKit
      3 
      4 /// Reads only an already-owned native response. Never enqueues or retries work.
      5 enum TeraStoppedUploadRecovery {
      6   static func receipt(_ submission: TeraSubmissionStatus, media: TeraPreparedMedia,
      7                       transfer: any RadrootsBackgroundTransfer) async throws -> TeraAddBackgroundUploadReceipt?
      8   {
      9     guard submission.delivery.isStopped,
     10           let item = submission.media.first(where: { $0.opaqueReference == media.opaqueReference }),
     11           item.progress.stage == .uploading else { throw TeraComposerAcknowledgment.unconfirmed }
     12     let snapshots = try await transfer.snapshots()
     13     try Task.checkCancellation()
     14     let candidates = try snapshots.filter { snapshot in
     15       guard snapshot.identifier.rawValue.hasPrefix("radroots.add.\(submission.intentID).") else { return false }
     16       guard let identity = TeraBackgroundUploadRequest.transferIdentity(snapshot.identifier),
     17             identity.draftID == submission.intentID, identity.revision <= submission.revision
     18       else { throw TeraComposerAcknowledgment.unconfirmed }
     19       guard snapshot.request.expectedSourceSHA256 == media.sha256 else { return false }
     20       guard try TeraBackgroundUploadRequest.persistedRequestMatchesMedia(
     21         snapshot.request, media: media, uploadURL: item.progress.uploadURL
     22       ) else { throw TeraComposerAcknowledgment.unconfirmed }
     23       return true
     24     }
     25     guard candidates.count <= 1 else { throw TeraComposerAcknowledgment.unconfirmed }
     26     guard let snapshot = candidates.first,
     27           let identity = TeraBackgroundUploadRequest.transferIdentity(snapshot.identifier),
     28           [.awaitingVerification, .completed].contains(snapshot.state) else { return nil }
     29     guard let response = snapshot.response, let status = UInt16(exactly: response.statusCode),
     30           let body = response.body else { throw TeraComposerAcknowledgment.unconfirmed }
     31     return TeraAddBackgroundUploadReceipt(identifier: snapshot.identifier.rawValue, draftID: submission.intentID,
     32                                           expectedRevision: identity.revision, statusCode: status,
     33                                           mediaType: response.mediaType, contentEncoding: response.contentEncoding, body: body)
     34   }
     35 }