amplify-swift/AmplifyTests/CoreTests/Operations/LongOperation.swift

139 lines
3.8 KiB
Swift

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
import Foundation
#if canImport(Combine)
import Combine
#endif
import Amplify
public class LongOperationRequest: AmplifyOperationRequest, RequestIdentifier {
public let options: [AnyHashable : Any]
public let steps: Int
public let delay: Double
public let requestID: String
public init(options: [AnyHashable : Any] = [:], steps: Int, delay: Double) {
self.options = options
self.steps = steps
self.delay = delay
self.requestID = UUID().uuidString
}
}
public struct LongOperationSuccess {
let id = UUID().uuidString
}
public enum LongOperationError: AmplifyError {
case unknown(ErrorDescription, Error? = nil)
public var errorDescription: ErrorDescription {
switch self {
case .unknown(let errorDescription, _):
return "Unexpected error occurred with message: \(errorDescription)"
}
}
public var recoverySuggestion: RecoverySuggestion {
switch self {
case .unknown:
return "No suggestion"
}
}
public var underlyingError: Error? {
switch self {
case .unknown(_, let error):
return error
}
}
public init(
errorDescription: ErrorDescription = "An unknown error occurred",
recoverySuggestion: RecoverySuggestion = "(Ignored)",
error: Error
) {
if let error = error as? Self {
self = error
} else {
self = .unknown(errorDescription, error)
}
}
}
public typealias LongOperationResult = Result<LongOperationSuccess, LongOperationError>
public typealias LongOperationProgressListener = (Progress) -> Void
public typealias LongOperationResultListener = (LongOperationResult) -> Void
public class LongOperation: AmplifyInProcessReportingOperation<LongOperationRequest, Progress, LongOperationSuccess, LongOperationError> {
public typealias TaskAdapter = AmplifyInProcessReportingOperationTaskAdapter<Request, InProcess, Success, Failure>
#if canImport(Combine)
public typealias ResultPublisher = AnyPublisher<Success, Failure>
public typealias ProgressPublisher = AnyPublisher<InProcess, Failure>
#endif
var count = 0
var currentProgress: Progress!
public init(request: LongOperationRequest,
progressListener: LongOperationProgressListener? = nil,
resultListener: LongOperationResultListener? = nil) {
super.init(categoryType: .storage, eventName: "LongOperation",
request: request,
inProcessListener: progressListener,
resultListener: resultListener)
}
public override func main() {
if isCancelled {
finish()
return
}
currentProgress = Progress(totalUnitCount: Int64(request.steps))
work()
}
private func work() {
if isCancelled {
finish()
return
}
reportProgress()
if count < request.steps {
DispatchQueue.global().asyncAfter(deadline: .now() + request.delay, execute: advance)
} else {
dispatch(result: .success(LongOperationSuccess()))
finish()
}
}
private func advance() {
count += 1
work()
}
private func reportProgress() {
currentProgress.completedUnitCount = Int64(count)
dispatchInProcess(data: currentProgress)
}
}
public typealias LongTask = LongOperation.TaskAdapter
#if canImport(Combine)
public typealias LongResultPublisher = LongOperation.ResultPublisher
public typealias LongProgressPublisher = LongOperation.ProgressPublisher
#endif
public extension HubPayload.EventName.Testing {
static let longCompositeTask = "Testing.longCompositeTask"
}