Skip to content

Commit

Permalink
add ability to specify callback queue and have chain return value as …
Browse files Browse the repository at this point in the history
…funnel to callback queue
  • Loading branch information
designatednerd committed Aug 4, 2020
1 parent e0e0664 commit e246d86
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 12 deletions.
3 changes: 2 additions & 1 deletion Sources/Apollo/FinalizingInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class FinalizingInterceptor: ApolloInterceptor {
return
}

completion(.success(parsed))
chain.returnValueAsync(value: parsed,
completion: completion)
}
}
9 changes: 6 additions & 3 deletions Sources/Apollo/LegacyCacheReadInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public class LegacyCacheReadInterceptor: ApolloInterceptor {
response: response,
completion: completion)
case .success(let graphQLResult):
completion(.success(graphQLResult as! ParsedValue))
chain.returnValueAsync(value: graphQLResult as! ParsedValue,
completion: completion)
}

// In either case, keep going asynchronously
Expand All @@ -65,7 +66,8 @@ public class LegacyCacheReadInterceptor: ApolloInterceptor {
completion: completion)
case .success(let graphQLResult):
// Cache hit! We're done.
completion(.success(graphQLResult as! ParsedValue))
chain.returnValueAsync(value: graphQLResult as! ParsedValue,
completion: completion)
}
}
case .returnCacheDataDontFetch:
Expand All @@ -78,7 +80,8 @@ public class LegacyCacheReadInterceptor: ApolloInterceptor {
response: response,
completion: completion)
case .success(let result):
completion(.success(result as! ParsedValue))
chain.returnValueAsync(value: result as! ParsedValue,
completion: completion)
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/Apollo/LegacyCacheWriteInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ public class LegacyCacheWriteInterceptor: ApolloInterceptor {
preconditionFailure(String(describing: error))
}
}
completion(.success(result as! ParsedValue))

chain.returnValueAsync(value: result as! ParsedValue,
completion: completion)
}.catch { error in
chain.handleErrorAsync(error,
request: request,
Expand Down
5 changes: 4 additions & 1 deletion Sources/Apollo/NetworkFetchInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ public class NetworkFetchInterceptor: ApolloInterceptor, Cancellable {
do {
urlRequest = try request.toURLRequest()
} catch {
completion(.failure(error))
chain.handleErrorAsync(error,
request: request,
response: response,
completion: completion)
return
}

Expand Down
35 changes: 29 additions & 6 deletions Sources/Apollo/RequestChain.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import Foundation
#if !COCOAPODS
import ApolloCore
#endif

public class RequestChain: Cancellable {

Expand All @@ -9,21 +12,26 @@ public class RequestChain: Cancellable {

private let interceptors: [ApolloInterceptor]
private var currentIndex: Int
public private(set) var isCancelled: Bool = false
public private(set) var callbackQueue: DispatchQueue
public private(set) var isCancelled = Atomic<Bool>(false)

/// Helper var for readability in guard statements
public var isNotCancelled: Bool {
!self.isCancelled
!self.isCancelled.value
}

/// Something which allows additional error handling to occur when some kind of error has happened.
public var additionalErrorHandler: ApolloErrorInterceptor?

/// Creates a chain with the given interceptor array.
///
/// - Parameter interceptors: The interceptors to use.
public init(interceptors: [ApolloInterceptor]) {
/// - Parameters:
/// - interceptors: The array of interceptors to use.
/// - callbackQueue: The `DispatchQueue` to call back on when an error or result occurs. Defauls to `.main`.
public init(interceptors: [ApolloInterceptor],
callbackQueue: DispatchQueue = .main) {
self.interceptors = interceptors
self.callbackQueue = callbackQueue
self.currentIndex = 0
}

Expand Down Expand Up @@ -86,7 +94,7 @@ public class RequestChain: Cancellable {

/// Cancels the entire chain of interceptors.
public func cancel() {
self.isCancelled = true
self.isCancelled.value = true

// If an interceptor adheres to `Cancellable`, it should have its in-flight work cancelled as well.
for interceptor in self.interceptors {
Expand Down Expand Up @@ -132,7 +140,9 @@ public class RequestChain: Cancellable {
}

guard let additionalHandler = self.additionalErrorHandler else {
completion(.failure(error))
self.callbackQueue.async {
completion(.failure(error))
}
return
}

Expand All @@ -143,4 +153,17 @@ public class RequestChain: Cancellable {
response: response,
completion: completion)
}

public func returnValueAsync<ParsedValue: Parseable>(
value: ParsedValue,
completion: @escaping (Result<ParsedValue, Error>) -> Void) {

guard self.isNotCancelled else {
return
}

self.callbackQueue.async {
completion(.success(value))
}
}
}

0 comments on commit e246d86

Please sign in to comment.