summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPN/Operations
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2021-09-14 13:59:01 +0200
committerAndrej Mihajlov <and@mullvad.net>2021-09-15 10:54:31 +0200
commit76dd2c99bf92d608022efbf05ffcbfebda43e0c1 (patch)
tree8cccb074a033089ac531e425f4a825df62b616c3 /ios/MullvadVPN/Operations
parente553d10b869c46e7ab922b86c32f4bd016e4fdac (diff)
downloadmullvadvpn-76dd2c99bf92d608022efbf05ffcbfebda43e0c1.tar.xz
mullvadvpn-76dd2c99bf92d608022efbf05ffcbfebda43e0c1.zip
Operations: simplify AsyncOperation, remove advanced features
Diffstat (limited to 'ios/MullvadVPN/Operations')
-rw-r--r--ios/MullvadVPN/Operations/AnyOperationObserver.swift19
-rw-r--r--ios/MullvadVPN/Operations/AssociatedValue.swift31
-rw-r--r--ios/MullvadVPN/Operations/AsyncBlockOperation.swift5
-rw-r--r--ios/MullvadVPN/Operations/AsyncOperation.swift122
-rw-r--r--ios/MullvadVPN/Operations/DelayOperation.swift48
-rw-r--r--ios/MullvadVPN/Operations/InputOperation.swift103
-rw-r--r--ios/MullvadVPN/Operations/OperationBlockObserver.swift67
-rw-r--r--ios/MullvadVPN/Operations/OperationObserver.swift18
-rw-r--r--ios/MullvadVPN/Operations/OperationProtocol.swift20
-rw-r--r--ios/MullvadVPN/Operations/OutputOperation.swift50
-rw-r--r--ios/MullvadVPN/Operations/ResultOperation.swift63
-rw-r--r--ios/MullvadVPN/Operations/RetryOperation.swift120
-rw-r--r--ios/MullvadVPN/Operations/TransformOperation.swift50
-rw-r--r--ios/MullvadVPN/Operations/TransformOperationObserver.swift45
14 files changed, 27 insertions, 734 deletions
diff --git a/ios/MullvadVPN/Operations/AnyOperationObserver.swift b/ios/MullvadVPN/Operations/AnyOperationObserver.swift
deleted file mode 100644
index 9c394f8b5a..0000000000
--- a/ios/MullvadVPN/Operations/AnyOperationObserver.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// AnyOperationObserver.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-class AnyOperationObserver<OperationType: OperationProtocol>: OperationBlockObserver<OperationType> {
- init<T: OperationObserver>(_ observer: T) where T.OperationType == OperationType {
- super.init(
- willExecute: observer.operationWillExecute,
- willFinish: observer.operationWillFinish,
- didFinish: observer.operationDidFinish
- )
- }
-}
diff --git a/ios/MullvadVPN/Operations/AssociatedValue.swift b/ios/MullvadVPN/Operations/AssociatedValue.swift
deleted file mode 100644
index 6fc860dbf3..0000000000
--- a/ios/MullvadVPN/Operations/AssociatedValue.swift
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// AssociatedValue.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-/// A container type for storing associated values
-final class AssociatedValue<T>: NSObject {
- let value: T
- init(_ value: T) {
- self.value = value
- }
-
- class func get(object: Any, key: UnsafeRawPointer) -> T? {
- let container = objc_getAssociatedObject(object, key) as? AssociatedValue<T>
- return container?.value
- }
-
- class func set(object: Any, key: UnsafeRawPointer, value: T?) {
- objc_setAssociatedObject(
- object,
- key,
- value.flatMap { AssociatedValue($0) },
- .OBJC_ASSOCIATION_RETAIN_NONATOMIC
- )
- }
-}
diff --git a/ios/MullvadVPN/Operations/AsyncBlockOperation.swift b/ios/MullvadVPN/Operations/AsyncBlockOperation.swift
index c8f4287b32..a7f0ffdd29 100644
--- a/ios/MullvadVPN/Operations/AsyncBlockOperation.swift
+++ b/ios/MullvadVPN/Operations/AsyncBlockOperation.swift
@@ -10,7 +10,7 @@ import Foundation
/// Asynchronous block operation
class AsyncBlockOperation: AsyncOperation {
- private let block: (@escaping () -> Void) -> Void
+ private let block: ((@escaping () -> Void) -> Void)
init(_ block: @escaping (@escaping () -> Void) -> Void) {
self.block = block
@@ -18,9 +18,8 @@ class AsyncBlockOperation: AsyncOperation {
}
override func main() {
- self.block { [weak self] in
+ block { [weak self] in
self?.finish()
}
}
}
-
diff --git a/ios/MullvadVPN/Operations/AsyncOperation.swift b/ios/MullvadVPN/Operations/AsyncOperation.swift
index 44e8e791f3..2d1819ee30 100644
--- a/ios/MullvadVPN/Operations/AsyncOperation.swift
+++ b/ios/MullvadVPN/Operations/AsyncOperation.swift
@@ -9,17 +9,10 @@
import Foundation
/// A base implementation of an asynchronous operation
-class AsyncOperation: Operation, OperationProtocol {
-
- /// A state transaction lock used to perform critical sections of code within `start`, `cancel`
- /// and `finish` calls.
- fileprivate let transactionLock = NSRecursiveLock()
+class AsyncOperation: Operation {
/// A state lock used for manipulating the operation state flags in a thread safe fashion.
- fileprivate let stateLock = NSRecursiveLock()
-
- /// The operation observers.
- fileprivate var observers: [AnyOperationObserver<AsyncOperation>] = []
+ private let stateLock = NSRecursiveLock()
/// Operation state flags.
private var _isExecuting = false
@@ -43,14 +36,14 @@ class AsyncOperation: Operation, OperationProtocol {
}
final override func start() {
- transactionLock.withCriticalBlock {
- if self.isCancelled {
- self.finish()
- } else {
- self.observers.forEach { $0.operationWillExecute(self) }
- self.setExecuting(true)
- self.main()
- }
+ stateLock.lock()
+ if _isCancelled {
+ finish()
+ stateLock.unlock()
+ } else {
+ setExecuting(true)
+ stateLock.unlock()
+ main()
}
}
@@ -58,99 +51,34 @@ class AsyncOperation: Operation, OperationProtocol {
// Override in subclasses
}
- /// Cancel operation
- /// Subclasses should override `operationDidCancel` instead
- final override func cancel() {
- transactionLock.withCriticalBlock {
- if self.isCancelled {
- super.cancel()
- } else {
- self.setCancelled(true)
-
- super.cancel()
-
- // Only notify the operation about cancellation when it is already running,
- // otherwise the call to `start` should automatically `finish()` the operation.
- if self.isExecuting {
- self.operationDidCancel()
- }
+ override func cancel() {
+ stateLock.withCriticalBlock {
+ if !_isCancelled {
+ willChangeValue(for: \.isCancelled)
+ _isCancelled = true
+ didChangeValue(for: \.isCancelled)
}
}
- }
-
- /// Override in subclasses to support task cancellation.
- /// Subclasses should call `finish()` to complete the operation
- func operationDidCancel() {
- // no-op
+ super.cancel()
}
final func finish() {
- transactionLock.withCriticalBlock {
- guard !self.isFinished else { return }
-
- self.stateLock.withCriticalBlock {
- self.observers.forEach { $0.operationWillFinish(self) }
- }
-
- if self.isExecuting {
- self.setExecuting(false)
+ stateLock.withCriticalBlock {
+ if _isExecuting {
+ setExecuting(false)
}
- self.setFinished(true)
-
- self.stateLock.withCriticalBlock {
- self.observers.forEach { $0.operationDidFinish(self) }
+ if !_isFinished {
+ willChangeValue(for: \.isFinished)
+ _isFinished = true
+ didChangeValue(for: \.isFinished)
}
}
}
private func setExecuting(_ value: Bool) {
willChangeValue(for: \.isExecuting)
- stateLock.withCriticalBlock { _isExecuting = value }
+ _isExecuting = value
didChangeValue(for: \.isExecuting)
}
-
- private func setFinished(_ value: Bool) {
- willChangeValue(for: \.isFinished)
- stateLock.withCriticalBlock { _isFinished = value }
- didChangeValue(for: \.isFinished)
- }
-
- private func setCancelled(_ value: Bool) {
- willChangeValue(for: \.isCancelled)
- stateLock.withCriticalBlock { _isCancelled = value }
- didChangeValue(for: \.isCancelled)
- }
-
- // MARK: - Observation
-
- /// Add type-erased operation observer
- fileprivate func addAnyObserver(_ observer: AnyOperationObserver<AsyncOperation>) {
- stateLock.withCriticalBlock {
- self.observers.append(observer)
- }
- }
-}
-
-/// This extension exists because Swift has some issues with infering the associated type in `OperationObserver`
-extension OperationProtocol where Self: AsyncOperation {
- func addObserver<T: OperationObserver>(_ observer: T) where T.OperationType == Self {
- let transform = TransformOperationObserver<AsyncOperation>(observer)
- let wrapped = AnyOperationObserver(transform)
- addAnyObserver(wrapped)
- }
-}
-
-
-protocol OperationSubclassing {
- /// Use this method in subclasses or extensions where you would like to synchronize
- /// the class members access using the same lock used for guarding from race conditions
- /// when managing operation state.
- func synchronized<T>(_ body: () -> T) -> T
-}
-
-extension AsyncOperation: OperationSubclassing {
- func synchronized<T>(_ body: () -> T) -> T {
- return stateLock.withCriticalBlock(body)
- }
}
diff --git a/ios/MullvadVPN/Operations/DelayOperation.swift b/ios/MullvadVPN/Operations/DelayOperation.swift
deleted file mode 100644
index 80719b573d..0000000000
--- a/ios/MullvadVPN/Operations/DelayOperation.swift
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// DelayOperation.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-enum DelayTimerType {
- case deadline
- case walltime
-}
-
-class DelayOperation: AsyncOperation {
- private let delay: TimeInterval
- private let timerType: DelayTimerType
- private var timer: DispatchSourceTimer?
-
- init(delay: TimeInterval, timerType: DelayTimerType) {
- self.delay = delay
- self.timerType = timerType
- }
-
- override func main() {
- let timer = DispatchSource.makeTimerSource()
- timer.setEventHandler { [weak self] in
- self?.finish()
- }
-
- switch timerType {
- case .deadline:
- timer.schedule(deadline: DispatchTime.now() + delay)
- case .walltime:
- timer.schedule(wallDeadline: DispatchWallTime.now() + delay)
- }
-
- self.timer = timer
- timer.activate()
- }
-
- override func operationDidCancel() {
- timer?.cancel()
- timer = nil
- finish()
- }
-}
diff --git a/ios/MullvadVPN/Operations/InputOperation.swift b/ios/MullvadVPN/Operations/InputOperation.swift
deleted file mode 100644
index a1c9d6931d..0000000000
--- a/ios/MullvadVPN/Operations/InputOperation.swift
+++ /dev/null
@@ -1,103 +0,0 @@
-//
-// InputOperation.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-protocol InputOperation: OperationProtocol {
- associatedtype Input
-
- /// When overriding `input` in Subclasses, make sure to call `operationDidSetInput`
- var input: Input? { get set }
-
- func operationDidSetInput(_ input: Input?)
-}
-
-private var kInputOperationAssociatedValue = 0
-extension InputOperation where Self: OperationSubclassing {
- var input: Input? {
- get {
- return synchronized {
- return AssociatedValue.get(object: self, key: &kInputOperationAssociatedValue)
- }
- }
- set {
- synchronized {
- AssociatedValue.set(object: self, key: &kInputOperationAssociatedValue, value: newValue)
-
- operationDidSetInput(newValue)
- }
- }
- }
-
- func operationDidSetInput(_ input: Input?) {
- // Override in subclasses
- }
-}
-
-extension InputOperation {
-
- @discardableResult func inject<Dependency>(from dependency: Dependency, via block: @escaping (Dependency.Output) -> Input?) -> Self
- where Dependency: OutputOperation
- {
- let observer = OperationBlockObserver<Dependency>(willFinish: { [weak self] (operation) in
- guard let self = self else { return }
-
- if let output = operation.output {
- self.input = block(output)
- }
- })
- dependency.addObserver(observer)
- addDependency(dependency)
-
- return self
- }
-
- @discardableResult func injectResult<Dependency>(from dependency: Dependency) -> Self
- where Dependency: OutputOperation, Dependency.Output == Input?
- {
- return self.inject(from: dependency, via: { $0 })
- }
-
- /// Inject input from operation that outputs `Result<Input, Failure>`
- @discardableResult func injectResult<Dependency, Failure>(from dependency: Dependency) -> Self
- where Dependency: OutputOperation, Failure: Error, Dependency.Output == Result<Input, Failure>
- {
- return self.inject(from: dependency) { (output) -> Input? in
- switch output {
- case .success(let value):
- return value
- case .failure:
- return nil
- }
- }
- }
-
- /// Inject input from operation that outputs `Result<Input, Never>`
- @discardableResult func injectResult<Dependency>(from dependency: Dependency) -> Self
- where Dependency: OutputOperation, Dependency.Output == Result<Input, Never>
- {
- return self.inject(from: dependency) { (output) -> Input? in
- switch output {
- case .success(let value):
- return value
- }
- }
- }
-
- /// Inject input from operation that outputs `Result<Input?, Never>`
- @discardableResult func injectResult<Dependency>(from dependency: Dependency) -> Self
- where Dependency: OutputOperation, Dependency.Output == Result<Input?, Never>
- {
- return self.inject(from: dependency) { (output) -> Input? in
- switch output {
- case .success(let value):
- return value
- }
- }
- }
-}
diff --git a/ios/MullvadVPN/Operations/OperationBlockObserver.swift b/ios/MullvadVPN/Operations/OperationBlockObserver.swift
deleted file mode 100644
index 1ba2f1ae50..0000000000
--- a/ios/MullvadVPN/Operations/OperationBlockObserver.swift
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// OperationBlockObserver.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-class OperationBlockObserver<OperationType: OperationProtocol>: OperationObserver {
- private var willExecute: ((OperationType) -> Void)?
- private var willFinish: ((OperationType) -> Void)?
- private var didFinish: ((OperationType) -> Void)?
-
- let queue: DispatchQueue?
-
- init(
- queue: DispatchQueue? = nil,
- willExecute: ((OperationType) -> Void)? = nil,
- willFinish: ((OperationType) -> Void)? = nil,
- didFinish: ((OperationType) -> Void)? = nil
- ) {
- self.queue = queue
- self.willExecute = willExecute
- self.willFinish = willFinish
- self.didFinish = didFinish
- }
-
- func operationWillExecute(_ operation: OperationType) {
- if let willExecute = willExecute {
- scheduleEvent {
- willExecute(operation)
- }
- }
- }
-
- func operationWillFinish(_ operation: OperationType) {
- if let willFinish = self.willFinish {
- scheduleEvent {
- willFinish(operation)
- }
- }
- }
-
- func operationDidFinish(_ operation: OperationType) {
- if let didFinish = self.didFinish {
- scheduleEvent {
- didFinish(operation)
- }
- }
- }
-
- private func scheduleEvent(_ body: @escaping () -> Void) {
- if let queue = queue {
- queue.async(execute: body)
- } else {
- body()
- }
- }
-}
-
-extension OperationProtocol {
- func addDidFinishBlockObserver(queue: DispatchQueue? = nil, _ block: @escaping (Self) -> Void) {
- addObserver(OperationBlockObserver(queue: queue, didFinish: block))
- }
-}
diff --git a/ios/MullvadVPN/Operations/OperationObserver.swift b/ios/MullvadVPN/Operations/OperationObserver.swift
deleted file mode 100644
index a7d3ea3aa3..0000000000
--- a/ios/MullvadVPN/Operations/OperationObserver.swift
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// OperationObserver.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-protocol OperationObserver {
- associatedtype OperationType: OperationProtocol
-
- func operationWillExecute(_ operation: OperationType)
- func operationWillFinish(_ operation: OperationType)
- func operationDidFinish(_ operation: OperationType)
-}
-
diff --git a/ios/MullvadVPN/Operations/OperationProtocol.swift b/ios/MullvadVPN/Operations/OperationProtocol.swift
deleted file mode 100644
index a41102c265..0000000000
--- a/ios/MullvadVPN/Operations/OperationProtocol.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// OperationProtocol.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-protocol OperationProtocol: Operation {
- /// Add operation observer
- func addObserver<T: OperationObserver>(_ observer: T) where T.OperationType == Self
-
- /// Finish operation
- func finish()
-
- /// Cancel operation
- func cancel()
-}
diff --git a/ios/MullvadVPN/Operations/OutputOperation.swift b/ios/MullvadVPN/Operations/OutputOperation.swift
deleted file mode 100644
index 064d54a2e9..0000000000
--- a/ios/MullvadVPN/Operations/OutputOperation.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// OutputOperation.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-protocol OutputOperation: OperationProtocol {
- associatedtype Output
-
- var output: Output? { get set }
-
- func finish(with output: Output)
-}
-
-extension OutputOperation {
- func finish(with output: Output) {
- self.output = output
- self.finish()
- }
-}
-
-private var kOutputOperationAssociatedValue = 0
-extension OutputOperation where Self: OperationSubclassing {
- var output: Output? {
- get {
- return synchronized {
- return AssociatedValue.get(object: self, key: &kOutputOperationAssociatedValue)
- }
- }
- set {
- synchronized {
- AssociatedValue.set(object: self, key: &kOutputOperationAssociatedValue, value: newValue)
- }
- }
- }
-}
-
-extension OperationProtocol where Self: OutputOperation {
- func addDidFinishBlockObserver(queue: DispatchQueue? = nil, _ block: @escaping (Self, Output) -> Void) {
- addDidFinishBlockObserver(queue: queue) { (operation) in
- if let output = operation.output {
- block(operation, output)
- }
- }
- }
-}
diff --git a/ios/MullvadVPN/Operations/ResultOperation.swift b/ios/MullvadVPN/Operations/ResultOperation.swift
deleted file mode 100644
index 7ce9c20358..0000000000
--- a/ios/MullvadVPN/Operations/ResultOperation.swift
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// ResultOperation.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-class ResultOperation<Success, Failure: Error>: AsyncOperation, OutputOperation {
- typealias Output = Result<Success, Failure>
-
- private enum Executor {
- case callback((@escaping (Result<Success, Failure>) -> Void) -> Void)
- case transform(() -> Result<Success, Failure>)
- }
-
- private let executor: Executor
-
- private init(_ executor: Executor) {
- self.executor = executor
- }
-
- convenience init(_ block: @escaping (@escaping (Output) -> Void) -> Void) {
- self.init(.callback(block))
- }
-
- convenience init(_ block: @escaping () -> Output) {
- self.init(.transform(block))
- }
-
- override func main() {
- switch executor {
- case .callback(let block):
- block { [weak self] (result) in
- self?.finish(with: result)
- }
-
- case .transform(let block):
- self.finish(with: block())
- }
- }
-
-}
-
-extension ResultOperation where Failure == Never {
- /// A convenience initializer for infallible `ResultOperation` that automatically wraps the
- /// return value of the given closure into `Result<Success, Never>`
- convenience init(_ block: @escaping () -> Success) {
- self.init(.transform({ .success(block()) }))
- }
-
- /// A convenience initializer for infallible `ResultOperation` that automatically wraps the
- /// value, passed to the given closure, into `Result<Success, Never>`
- convenience init(_ block: @escaping (@escaping (Success) -> Void) -> Void) {
- self.init(.callback({ (finish) in
- block {
- finish(.success($0))
- }
- }))
- }
-}
diff --git a/ios/MullvadVPN/Operations/RetryOperation.swift b/ios/MullvadVPN/Operations/RetryOperation.swift
deleted file mode 100644
index 1e73e81d79..0000000000
--- a/ios/MullvadVPN/Operations/RetryOperation.swift
+++ /dev/null
@@ -1,120 +0,0 @@
-//
-// RetryOperation.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-enum WaitStrategy {
- case immediate
- case constant(TimeInterval)
-
- var iterator: AnyIterator<TimeInterval> {
- switch self {
- case .immediate:
- return AnyIterator { .zero }
- case .constant(let constant):
- return AnyIterator { constant }
- }
- }
-}
-
-struct RetryStrategy {
- var maxRetries: Int
- var waitStrategy: WaitStrategy
- var waitTimerType: DelayTimerType
-}
-
-class RetryOperation<OperationType, Success, Failure: Error>: AsyncOperation, OutputOperation
- where OperationType: OutputOperation, OperationType.Output == Result<Success, Failure>
-{
- typealias Output = OperationType.Output
-
- private let operationQueue = OperationQueue()
-
- private let producer: () -> OperationType
- private let delayIterator: AnyIterator<TimeInterval>
-
- private var retryCount: Int = 0
- private let retryStrategy: RetryStrategy
-
- private var childConfigurator: ((OperationType) -> Void)?
-
- init(underlyingQueue: DispatchQueue? = nil, strategy: RetryStrategy, producer: @escaping () -> OperationType) {
- operationQueue.underlyingQueue = underlyingQueue
- delayIterator = strategy.waitStrategy.iterator
- retryStrategy = strategy
- self.producer = producer
- }
-
- override func main() {
- retry()
- }
-
- override func operationDidCancel() {
- operationQueue.cancelAllOperations()
- }
-
- private func retry(delay: TimeInterval? = nil) {
- let child = producer()
-
- child.addDidFinishBlockObserver { [weak self] (operation) in
- guard let self = self else { return }
-
- // Operation finished without output set?
- guard let result = operation.output else {
- self.finish()
- return
- }
-
- self.synchronized {
- guard case .failure(let error) = result,
- let delay = self.delayIterator.next(),
- self.shouldRetry(error: error) else {
- self.finish(with: result)
- return
- }
-
- self.retryCount += 1
- self.retry(delay: delay)
- }
- }
-
- synchronized {
- childConfigurator?(child)
- }
-
- if let delay = delay {
- let delayOperation = DelayOperation(delay: delay, timerType: retryStrategy.waitTimerType)
-
- child.addDependency(delayOperation)
- operationQueue.addOperation(delayOperation)
- }
-
- operationQueue.addOperation(child)
- }
-
- private func setChildConfigurator(_ body: @escaping (OperationType) -> Void) {
- synchronized {
- self.childConfigurator = body
- }
- }
-
- private func shouldRetry(error: Failure) -> Bool {
- return retryCount < retryStrategy.maxRetries && !self.isCancelled
- }
-
-}
-
-extension RetryOperation: InputOperation where OperationType: InputOperation {
- typealias Input = OperationType.Input
-
- func operationDidSetInput(_ input: OperationType.Input?) {
- setChildConfigurator { (child) in
- child.input = input
- }
- }
-}
diff --git a/ios/MullvadVPN/Operations/TransformOperation.swift b/ios/MullvadVPN/Operations/TransformOperation.swift
deleted file mode 100644
index ce2a1617ea..0000000000
--- a/ios/MullvadVPN/Operations/TransformOperation.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// TransformOperation.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-class TransformOperation<Input, Output>: AsyncOperation, InputOperation, OutputOperation {
- private enum Executor {
- case callback((Input, @escaping (Output) -> Void) -> Void)
- case transform((Input) -> Output)
- }
-
- private let executor: Executor
-
- private init(input: Input? = nil, executor: Executor) {
- self.executor = executor
-
- super.init()
- self.input = input
- }
-
- convenience init(input: Input? = nil, _ block: @escaping (Input, @escaping (Output) -> Void) -> Void) {
- self.init(input: input, executor: .callback(block))
- }
-
- convenience init(input: Input? = nil, _ block: @escaping (Input) -> Output) {
- self.init(input: input, executor: .transform(block))
- }
-
- override func main() {
- guard let input = input else {
- self.finish()
- return
- }
-
- switch executor {
- case .callback(let block):
- block(input) { [weak self] (result) in
- self?.finish(with: result)
- }
-
- case .transform(let block):
- self.finish(with: block(input))
- }
- }
-}
diff --git a/ios/MullvadVPN/Operations/TransformOperationObserver.swift b/ios/MullvadVPN/Operations/TransformOperationObserver.swift
deleted file mode 100644
index e6ed695e0b..0000000000
--- a/ios/MullvadVPN/Operations/TransformOperationObserver.swift
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// TransformOperationObserver.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-/// A private type erasing observer that type casts the input operation type to the expected
-/// operation type before calling the wrapped observer
-class TransformOperationObserver<S: OperationProtocol>: OperationObserver {
- private let willExecute: (S) -> Void
- private let willFinish: (S) -> Void
- private let didFinish: (S) -> Void
-
- init<T: OperationObserver>(_ observer: T) {
- willExecute = Self.wrap(observer.operationWillExecute)
- willFinish = Self.wrap(observer.operationWillFinish)
- didFinish = Self.wrap(observer.operationDidFinish)
- }
-
- func operationWillExecute(_ operation: S) {
- willExecute(operation)
- }
-
- func operationWillFinish(_ operation: S) {
- willFinish(operation)
- }
-
- func operationDidFinish(_ operation: S) {
- didFinish(operation)
- }
-
- private class func wrap<U>(_ body: @escaping (U) -> Void) -> (S) -> Void {
- return { (operation: S) in
- if let transformed = operation as? U {
- body(transformed)
- } else {
- fatalError("\(Self.self) failed to cast \(S.self) to \(U.self)")
- }
- }
- }
-}