Error handling refactor (#170)

* Improve error handling on processor and service

* Error Refactoring

* fix XCode12 issue

* Fix Compilation errors and test

* bump MIDDLE version
This commit is contained in:
Francisco Gindre 2020-08-10 19:19:59 -03:00 committed by GitHub
parent b214a19724
commit 251b4c7aa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 263 additions and 142 deletions

View File

@ -6,7 +6,7 @@ target 'ZcashLightClientSample' do
pod "KRProgressHUD"
# Pods for ZcashLightClientSample
pod 'ZcashLightClientKit', :path => '../../', :testspecs => ['Tests']
pod 'gRPC-Swift', '~> 1.0.0-alpha.11'
pod 'gRPC-Swift', '= 1.0.0-alpha.17'
pod 'PaginatedTableView'
pod 'NotificationBubbles'
pod 'MnemonicSwift'

View File

@ -1,78 +1,78 @@
PODS:
- CGRPCZlib (1.0.0-alpha.14)
- CNIOAtomics (2.18.0)
- CNIOBoringSSL (2.7.4)
- CNIOBoringSSLShims (2.7.4):
- CNIOBoringSSL (= 2.7.4)
- CNIODarwin (2.18.0)
- CNIOHTTPParser (2.18.0)
- CNIOLinux (2.18.0)
- CNIOSHA1 (2.18.0)
- gRPC-Swift (1.0.0-alpha.14):
- CGRPCZlib (= 1.0.0-alpha.14)
- CGRPCZlib (1.0.0-alpha.17)
- CNIOAtomics (2.20.2)
- CNIOBoringSSL (2.9.0)
- CNIOBoringSSLShims (2.9.0):
- CNIOBoringSSL (= 2.9.0)
- CNIODarwin (2.20.2)
- CNIOHTTPParser (2.20.2)
- CNIOLinux (2.20.2)
- CNIOSHA1 (2.20.2)
- gRPC-Swift (1.0.0-alpha.17):
- CGRPCZlib (= 1.0.0-alpha.17)
- Logging (< 2, >= 1.2.0)
- SwiftNIO (< 3, >= 2.18.0)
- SwiftNIO (< 3, >= 2.19.0)
- SwiftNIOHTTP2 (< 2, >= 1.12.2)
- SwiftNIOSSL (< 3, >= 2.7.4)
- SwiftNIOSSL (< 3, >= 2.8.0)
- SwiftNIOTransportServices (< 2, >= 1.6.0)
- SwiftProtobuf (< 2, >= 1.9.0)
- KRActivityIndicatorView (3.0.5)
- KRProgressHUD (3.4.5):
- KRActivityIndicatorView (= 3.0.5)
- Logging (1.2.0)
- Logging (1.4.0)
- MnemonicSwift (1.0.0)
- NotificationBubbles (0.1.1)
- PaginatedTableView (1.0.1)
- SQLite.swift (0.12.2):
- SQLite.swift/standard (= 0.12.2)
- SQLite.swift/standard (0.12.2)
- SwiftNIO (2.18.0):
- CNIOAtomics (= 2.18.0)
- CNIODarwin (= 2.18.0)
- CNIOLinux (= 2.18.0)
- CNIOSHA1 (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOConcurrencyHelpers (2.18.0):
- CNIOAtomics (= 2.18.0)
- SwiftNIOFoundationCompat (2.18.0):
- SwiftNIO (= 2.18.0)
- SwiftNIOHPACK (1.12.2):
- SwiftNIO (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOHTTP1 (= 2.18.0)
- SwiftNIOHTTP1 (2.18.0):
- CNIOHTTPParser (= 2.18.0)
- SwiftNIO (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOHTTP2 (1.12.2):
- SwiftNIO (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOHPACK (= 1.12.2)
- SwiftNIOHTTP1 (= 2.18.0)
- SwiftNIOTLS (= 2.18.0)
- SwiftNIOSSL (2.7.4):
- CNIOBoringSSL (= 2.7.4)
- CNIOBoringSSLShims (= 2.7.4)
- SwiftNIO (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOTLS (= 2.18.0)
- SwiftNIOTLS (2.18.0):
- SwiftNIO (= 2.18.0)
- SwiftNIOTransportServices (1.6.0):
- SwiftNIO (~> 2.0)
- SwiftNIOConcurrencyHelpers (~> 2.0)
- SwiftNIOFoundationCompat (~> 2.0)
- SwiftNIOTLS (~> 2.0)
- SwiftProtobuf (1.9.0)
- SwiftNIO (2.20.2):
- CNIOAtomics (= 2.20.2)
- CNIODarwin (= 2.20.2)
- CNIOLinux (= 2.20.2)
- CNIOSHA1 (= 2.20.2)
- SwiftNIOConcurrencyHelpers (= 2.20.2)
- SwiftNIOConcurrencyHelpers (2.20.2):
- CNIOAtomics (= 2.20.2)
- SwiftNIOFoundationCompat (2.20.2):
- SwiftNIO (= 2.20.2)
- SwiftNIOHPACK (1.13.0):
- SwiftNIO (< 3, >= 2.19.0)
- SwiftNIOConcurrencyHelpers (< 3, >= 2.19.0)
- SwiftNIOHTTP1 (< 3, >= 2.19.0)
- SwiftNIOHTTP1 (2.20.2):
- CNIOHTTPParser (= 2.20.2)
- SwiftNIO (= 2.20.2)
- SwiftNIOConcurrencyHelpers (= 2.20.2)
- SwiftNIOHTTP2 (1.13.0):
- SwiftNIO (< 3, >= 2.19.0)
- SwiftNIOConcurrencyHelpers (< 3, >= 2.19.0)
- SwiftNIOHPACK (= 1.13.0)
- SwiftNIOHTTP1 (< 3, >= 2.19.0)
- SwiftNIOTLS (< 3, >= 2.19.0)
- SwiftNIOSSL (2.9.0):
- CNIOBoringSSL (= 2.9.0)
- CNIOBoringSSLShims (= 2.9.0)
- SwiftNIO (< 3, >= 2.19.0)
- SwiftNIOConcurrencyHelpers (< 3, >= 2.19.0)
- SwiftNIOTLS (< 3, >= 2.19.0)
- SwiftNIOTLS (2.20.2):
- SwiftNIO (= 2.20.2)
- SwiftNIOTransportServices (1.8.0):
- SwiftNIO (< 3, >= 2.19.0)
- SwiftNIOConcurrencyHelpers (< 3, >= 2.19.0)
- SwiftNIOFoundationCompat (< 3, >= 2.19.0)
- SwiftNIOTLS (< 3, >= 2.19.0)
- SwiftProtobuf (1.11.0)
- ZcashLightClientKit (0.5.3):
- gRPC-Swift (~> 1.0.0-alpha.11)
- gRPC-Swift (~> 1.0.0-alpha.17)
- SQLite.swift (~> 0.12.2)
- ZcashLightClientKit/Tests (0.5.3):
- gRPC-Swift (~> 1.0.0-alpha.11)
- gRPC-Swift (~> 1.0.0-alpha.11, ~> 1.0.0-alpha.17)
- SQLite.swift (~> 0.12.2)
DEPENDENCIES:
- gRPC-Swift (~> 1.0.0-alpha.11)
- gRPC-Swift (= 1.0.0-alpha.17)
- KRProgressHUD
- MnemonicSwift
- NotificationBubbles
@ -114,34 +114,34 @@ EXTERNAL SOURCES:
:path: "../../"
SPEC CHECKSUMS:
CGRPCZlib: 06247b0687f3a3edbfbfb204d53721c3ba262a34
CNIOAtomics: b6053043649c8b9afbf2560d9d64899d5d7ce368
CNIOBoringSSL: 21bbd36e5a68c9d2ea1aea7bfea10eea60d25a82
CNIOBoringSSLShims: e9e57b1fd0e060a25f2f3b0b944cc84dd272368f
CNIODarwin: 2e814fe13ee1b16a6d7603affbd95b3fbf1e65b1
CNIOHTTPParser: 215fe669981deb6b7e4533b0b42a01e5c165d8ac
CNIOLinux: 45e91eaba50bb850a48135aabbd7671625f15188
CNIOSHA1: f8f5b0c8cbd067c195d1b44ab237927765bd4914
gRPC-Swift: fb8ff0d8cdd5a020c170ba827f50c393ae31e307
CGRPCZlib: 245283cd656bf0c309a48a887c27865d6f54f7ef
CNIOAtomics: 7daf6423d00650104436c5f8a2a341679104ae83
CNIOBoringSSL: fb66746214b40dded1a8ddf2e078af0eff07bfb8
CNIOBoringSSLShims: c7a6e1e29088739872e51f70f8305beadfa6ca61
CNIODarwin: 65509d8e6a65a3f3f7bf5b09455cbabd535f48f3
CNIOHTTPParser: ec6aa14852274b383a52bacd4d6bb3d2432a50e9
CNIOLinux: 380e2601f1f32f8f32a78437c5f4f5a688205e2b
CNIOSHA1: 5cc4fc5054beeb21c8e0017ad6bf559ce8095c10
gRPC-Swift: 871cf2df24d9f5424763ae5af7248ed26a1b1314
KRActivityIndicatorView: 912bc0413d98340f384b12a4e1e6aa8f42fb377d
KRProgressHUD: df4cdc3a1baf708d4276a089ee34d133fa9a6f3e
Logging: 7838d379d234d7e5ae1265fa02804a9084caf04c
Logging: beeb016c9c80cf77042d62e83495816847ef108b
MnemonicSwift: d743ec3dcc1cdce706a1876dba0b6250ad1ef90d
NotificationBubbles: 91ee10deee54f35b5d49a161e1cb3d788ab5d011
PaginatedTableView: 294d9831d5ddf5c0dcfbb4a281d4fcfb8d12f55a
SQLite.swift: d2b4642190917051ce6bd1d49aab565fe794eea3
SwiftNIO: c17d311e9006fc10c1d17fbc6a7a9cb21aa46368
SwiftNIOConcurrencyHelpers: 69762a04ed76d7254012e1f17787ee162d2cf764
SwiftNIOFoundationCompat: 9af7b2e265c4d55eb8599a515d63784c2691dc39
SwiftNIOHPACK: 871e4e893ecc1aeaf74435b73c13240f50d6853c
SwiftNIOHTTP1: 67eafb3f27c3aee867dc4c0ec947e2ab71f1e2ce
SwiftNIOHTTP2: c7ce23b714868de63dae083478b40da20d933e08
SwiftNIOSSL: 0f28ad98a39b4c625196c2c8f154a4fded66bd96
SwiftNIOTLS: 78c6d6798ea29f7eb0a4e1214a00bc8f07e7390c
SwiftNIOTransportServices: 775bcda101a0d921feb69d79b5884acfce0fc0f2
SwiftProtobuf: ecbec1be9036d15655f6b3443a1c4ea693c97932
ZcashLightClientKit: 45c910a419418feb081e53d179875f740091812e
SwiftNIO: a3c1b37da3e97ce44b3cfafc61c05fe0cac540b8
SwiftNIOConcurrencyHelpers: cd7afc3d1f1ceaf55bbd030e7d1a469d3024db92
SwiftNIOFoundationCompat: 573f44d5b24f7ead54b6b111264c0a420fc6eccf
SwiftNIOHPACK: 0346ad2091511232c8cf19a6183b9c96ce33baf3
SwiftNIOHTTP1: b54fae8700b647e908597aa7ed3370389f634b87
SwiftNIOHTTP2: 8a0f333b99f9283f457762f58baa30acfee354cb
SwiftNIOSSL: 3e67b565a567c20ed38586ae0b3566f190776a95
SwiftNIOTLS: 9225a214c2483873406322d83c9db3731d8350e9
SwiftNIOTransportServices: e69704b2d41b68a531bf3aa0177fec81ba1361e6
SwiftProtobuf: f889fe5772f90ef7d7b8aac352d1fddf39650713
ZcashLightClientKit: 52c03806e721784c91b87a2ab038ee302e1635b9
PODFILE CHECKSUM: 191070101f577589f53b033656190b612695c5f7
PODFILE CHECKSUM: 0055c060ebfda59d4243e428eedc1db06c245f19
COCOAPODS: 1.9.3

View File

@ -10,7 +10,7 @@ import Foundation
import ZcashLightClientKit
import os
class SampleLogger: Logger {
class SampleLogger: ZcashLightClientKit.Logger {
enum LogLevel: Int {
case debug
case error

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'ZcashLightClientKit'
s.version = '0.5.3'
s.version = '0.6.0'
s.summary = 'Zcash Light Client wallet SDK for iOS'
s.description = <<-DESC
@ -19,7 +19,7 @@ Pod::Spec.new do |s|
s.module_map = 'ZcashLightClientKit.modulemap'
s.swift_version = '5.1'
s.ios.deployment_target = '12.0'
s.dependency 'gRPC-Swift', '~> 1.0.0-alpha.11'
s.dependency 'gRPC-Swift', '~> 1.0.0-alpha.17'
s.dependency 'SQLite.swift', '~> 0.12.2'
s.ios.vendored_libraries = 'lib/libzcashlc.a'
s.preserve_paths = ['Scripts', 'rust','docs','Cargo.*','ZcashLightClientKit/Stencil']

View File

@ -16,10 +16,13 @@ public enum CompactBlockProcessorError: Error {
case invalidConfiguration
case missingDbPath(path: String)
case dataDbInitFailed(path: String)
case connectionError(message: String)
case connectionError(underlyingError: Error)
case grpcError(statusCode: Int, message: String)
case connectionTimeout
case generalError(message: String)
case maxAttemptsReached(attempts: Int)
case unspecifiedError(underlyingError: Error)
case criticalError
}
/**
CompactBlockProcessor notification userInfo object keys.
@ -686,16 +689,9 @@ public class CompactBlockProcessor {
NotificationCenter.default.post(name: Notification.Name.blockProcessorFailed, object: self, userInfo: [CompactBlockProcessorNotificationKey.error: mapError(err)])
}
// TODO: encapsulate service errors better
func mapError(_ error: Error) -> Error {
func mapError(_ error: Error) -> CompactBlockProcessorError {
if let lwdError = error as? LightWalletServiceError {
switch lwdError {
case .failed(let statusCode, let message):
return CompactBlockProcessorError.connectionError(message: "Connection failed - Status code: \(statusCode) - message: \(message)")
case .invalidBlock:
return CompactBlockProcessorError.generalError(message: "Invalid block: \(lwdError)")
default:
return CompactBlockProcessorError.generalError(message: "Error: \(lwdError)")
}
return lwdError.mapToProcessorError()
} else if let rpcError = error as? GRPC.GRPCStatus {
switch rpcError {
case .ok:
@ -707,7 +703,7 @@ public class CompactBlockProcessor {
}
}
return error
return .unspecifiedError(underlyingError: error)
}
}
@ -721,6 +717,30 @@ public extension CompactBlockProcessor.Configuration {
}
}
extension LightWalletServiceError {
func mapToProcessorError() -> CompactBlockProcessorError {
switch self {
case .failed(let statusCode, let message):
return CompactBlockProcessorError.grpcError(statusCode: statusCode, message: message)
case .invalidBlock:
return CompactBlockProcessorError.generalError(message: "\(self)")
case .generalError(let message):
return CompactBlockProcessorError.generalError(message: message)
case .sentFailed(let error):
return CompactBlockProcessorError.connectionError(underlyingError: error)
case .genericError(let error):
return CompactBlockProcessorError.unspecifiedError(underlyingError: error)
case .timeOut:
return CompactBlockProcessorError.connectionTimeout
case .criticalError:
return CompactBlockProcessorError.criticalError
case .userCancelled:
return CompactBlockProcessorError.connectionTimeout
case .unknown:
return CompactBlockProcessorError.unspecifiedError(underlyingError: self)
}
}
}
extension CompactBlockProcessor.State: Equatable {
public static func == (lhs: CompactBlockProcessor.State, rhs: CompactBlockProcessor.State) -> Bool {
switch lhs {

View File

@ -9,8 +9,24 @@
import Foundation
import GRPC
import NIO
import NIOHPACK
public typealias Channel = GRPC.GRPCChannel
extension TimeAmount {
static let singleCallTimeout = TimeAmount.seconds(10)
static let streamingCallTimeout = TimeAmount.seconds(90)
}
extension CallOptions {
static var lwdCall: CallOptions {
CallOptions(customMetadata: HPACKHeaders(),
timeLimit: .timeout(.singleCallTimeout),
messageEncoding: .disabled,
requestIDProvider: .autogenerated,
requestIDHeader: nil,
cacheable: false)
}
}
/**
Swift GRPC implementation of Lightwalletd service */
public class LightWalletGRPCService {
@ -22,7 +38,7 @@ public class LightWalletGRPCService {
public init(channel: Channel) {
self.channel = channel
compactTxStreamer = CompactTxStreamerClient(channel: self.channel)
compactTxStreamer = CompactTxStreamerClient(channel: self.channel, defaultCallOptions: CallOptions.lwdCall)
}
public convenience init(endpoint: LightWalletEndpoint) {
@ -59,9 +75,14 @@ extension LightWalletGRPCService: LightWalletService {
public func fetchTransaction(txId: Data) throws -> TransactionEntity {
var txFilter = TxFilter()
txFilter.hash = txId
let rawTx = try compactTxStreamer.getTransaction(txFilter).response.wait()
return TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)
do {
let rawTx = try compactTxStreamer.getTransaction(txFilter).response.wait()
return TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)
} catch {
throw error.mapToServiceError()
}
}
public func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void) {
@ -73,7 +94,7 @@ extension LightWalletGRPCService: LightWalletService {
switch response {
case .failure(let error):
result(.failure(LightWalletServiceError.genericError(error: error)))
result(.failure(error.mapToServiceError()))
case .success(let rawTx):
result(.success(TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)))
}
@ -88,13 +109,13 @@ extension LightWalletGRPCService: LightWalletService {
response.whenComplete { (responseResult) in
switch responseResult {
case .failure(let e):
result(.failure(LightWalletServiceError.genericError(error: e)))
result(.failure(LightWalletServiceError.sentFailed(error: e)))
case .success(let s):
result(.success(s))
}
}
} catch {
result(.failure(LightWalletServiceError.genericError(error: error)))
result(.failure(error.mapToServiceError()))
}
}
@ -103,7 +124,11 @@ extension LightWalletGRPCService: LightWalletService {
let rawTx = RawTransaction.with { (raw) in
raw.data = spendTransaction
}
return try compactTxStreamer.sendTransaction(rawTx).response.wait()
do {
return try compactTxStreamer.sendTransaction(rawTx).response.wait()
} catch {
throw error.mapToServiceError()
}
}
public func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
@ -113,18 +138,21 @@ extension LightWalletGRPCService: LightWalletService {
blocks.append($0)
})
do {
_ = try response.status.wait()
} catch {
throw LightWalletServiceError.genericError(error: error)
let status = try response.status.wait()
switch status.code {
case .ok:
do {
return try blocks.asZcashCompactBlocks()
} catch {
LoggerProxy.error("invalid block in range: \(range) - Error: \(error)")
throw LightWalletServiceError.genericError(error: error)
}
default:
throw LightWalletServiceError.mapCode(status)
}
do {
return try blocks.asZcashCompactBlocks()
} catch {
LoggerProxy.error("invalid block in range: \(range) - Error: \(error)")
throw LightWalletServiceError.genericError(error: error)
}
}
public func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
@ -132,19 +160,18 @@ extension LightWalletGRPCService: LightWalletService {
response.whenSuccess { (blockID) in
guard let blockHeight = Int(exactly: blockID.height) else {
result(.failure(LightWalletServiceError.generalError))
result(.failure(LightWalletServiceError.generalError(message: "error creating blockheight from BlockID \(blockID)")))
return
}
result(.success(blockHeight))
}
response.whenFailure { (error) in
result(.failure(LightWalletServiceError.genericError(error: error)))
result(.failure(error.mapToServiceError()))
}
}
// TODO: Make cancellable
public func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
queue.async { [weak self] in
@ -162,15 +189,16 @@ extension LightWalletGRPCService: LightWalletService {
do {
result(.success(try blocks.asZcashCompactBlocks()))
} catch {
result(.failure(LightWalletServiceError.generalError))
LoggerProxy.error("Error parsing compact blocks \(error)")
result(.failure(LightWalletServiceError.invalidBlock))
}
default:
result(Result.failure(LightWalletServiceError.failed(statusCode: status.code.rawValue, message: status.message ?? "No Message")))
result(.failure(.mapCode(status)))
}
} catch {
result(.failure(LightWalletServiceError.genericError(error: error)))
result(.failure(error.mapToServiceError()))
}
}
@ -184,5 +212,34 @@ extension LightWalletGRPCService: LightWalletService {
}
return height
}
}
extension Error {
func mapToServiceError() -> LightWalletServiceError {
guard let grpcError = self as? GRPCStatusTransformable
else {
return LightWalletServiceError.genericError(error: self)
}
return LightWalletServiceError.mapCode(grpcError.makeGRPCStatus())
}
}
extension LightWalletServiceError {
static func mapCode(_ status: GRPCStatus) -> LightWalletServiceError {
switch status.code {
case .ok:
return LightWalletServiceError.unknown
case .cancelled:
return LightWalletServiceError.userCancelled
case .unknown:
return LightWalletServiceError.unknown
case .deadlineExceeded:
return LightWalletServiceError.timeOut
default:
return LightWalletServiceError.genericError(error: status)
}
}
}

View File

@ -14,20 +14,24 @@ import SwiftProtobuf
Wrapper for errors received from a Lightwalletd endpoint
*/
public enum LightWalletServiceError: Error {
case generalError
case generalError(message: String)
case failed(statusCode: Int, message: String)
case invalidBlock
case sentFailed(sendResponse: LightWalletServiceResponse)
case sentFailed(error: Error)
case genericError(error: Error)
case timeOut
case criticalError
case userCancelled
case unknown
}
extension LightWalletServiceError: Equatable {
public static func == (lhs: Self, rhs: Self) -> Bool {
switch lhs {
case .generalError:
case .generalError(let m):
switch rhs {
case .generalError:
return true
case .generalError(let msg):
return m == msg
default:
return false
}
@ -46,18 +50,46 @@ extension LightWalletServiceError: Equatable {
default:
return false
}
case .sentFailed(let sendResponse):
case .sentFailed(_):
switch rhs {
case .sentFailed(let response):
return response.errorCode == sendResponse.errorCode
case .sentFailed(_):
return true
default:
return false
}
case .genericError:
return false
case .timeOut:
switch rhs {
case .timeOut:
return true
default:
return false
}
case .criticalError:
switch rhs {
case .criticalError:
return true
default:
return false
}
case .userCancelled:
switch rhs {
case .userCancelled:
return true
default:
return false
}
case .unknown:
switch rhs {
case .unknown:
return true
default:
return false
}
}
}
}
public protocol LightWalletServiceResponse {

View File

@ -14,10 +14,13 @@ Represents errors thrown by a Synchronizer
public enum SynchronizerError: Error {
case initFailed(message: String)
case syncFailed
case connectionFailed(message: String)
case connectionFailed(message: Error)
case generalError(message: String)
case maxRetryAttemptsReached(attempts: Int)
case connectionError(status: Int, message: String)
case networkTimeout
case uncategorized(underlyingError: Error)
case criticalError
}
/**

View File

@ -142,15 +142,18 @@ public class SDKSynchronizer: Synchronizer {
return
}
try processor.start(retry: retry)
do {
try processor.start(retry: retry)
} catch {
throw mapError(error)
}
}
/**
Stops the synchronizer
- Throws: CompactBlockProcessorError when failures occur
*/
public func stop() throws {
public func stop() {
defer {
@ -329,6 +332,8 @@ public class SDKSynchronizer: Synchronizer {
guard let self = self else { return }
if let error = notification.userInfo?[CompactBlockProcessorNotificationKey.error] as? Error {
self.notifyFailure(error)
} else {
self.notifyFailure(CompactBlockProcessorError.generalError(message: "This is strange. processorFailed Call received no error message"))
}
self.status = .disconnected
}
@ -400,9 +405,7 @@ public class SDKSynchronizer: Synchronizer {
}
@objc func applicationWillTerminate(_ notification: Notification) {
do {
try stop()
} catch {}
stop()
}
// MARK: Synchronizer methods
@ -547,9 +550,15 @@ public class SDKSynchronizer: Synchronizer {
return SynchronizerError.maxRetryAttemptsReached(attempts: attempts)
case .grpcError(let statusCode, let message):
return SynchronizerError.connectionError(status: statusCode, message: message)
case .connectionTimeout:
return SynchronizerError.networkTimeout
case .unspecifiedError(let underlyingError):
return SynchronizerError.uncategorized(underlyingError: underlyingError)
case .criticalError:
return SynchronizerError.criticalError
}
}
return error
return SynchronizerError.uncategorized(underlyingError: error)
}
private func notifyFailure(_ error: Error) {

View File

@ -79,14 +79,14 @@ class CompactBlockReorgTests: XCTestCase {
}
@objc func processorFailed(_ notification: Notification) {
DispatchQueue.main.sync {
XCTAssertNotNil(notification.userInfo)
if let error = notification.userInfo?["error"] {
XCTFail("CompactBlockProcessor failed with Error: \(error)")
} else {
XCTFail("CompactBlockProcessor failed")
}
}
}
fileprivate func startProcessing() {

View File

@ -9,7 +9,7 @@
import Foundation
import os
import ZcashLightClientKit
class SampleLogger: Logger {
class SampleLogger: ZcashLightClientKit.Logger {
enum LogLevel: Int {
case debug
case error

View File

@ -13,7 +13,7 @@ import SwiftProtobuf
class AwfulLightWalletService: MockLightWalletService {
override func latestBlockHeight() throws -> BlockHeight {
throw LightWalletServiceError.generalError
throw LightWalletServiceError.criticalError
}
override func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
@ -22,20 +22,20 @@ class AwfulLightWalletService: MockLightWalletService {
override func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
result(.failure(LightWalletServiceError.generalError))
result(.failure(LightWalletServiceError.invalidBlock))
}
}
override func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
result(.failure(LightWalletServiceError.generalError))
result(.failure(LightWalletServiceError.invalidBlock))
}
}
override func submit(spendTransaction: Data, result: @escaping(Result<LightWalletServiceResponse,LightWalletServiceError>) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
result(.failure(LightWalletServiceError.generalError))
result(.failure(LightWalletServiceError.invalidBlock))
}
}
@ -44,7 +44,7 @@ class AwfulLightWalletService: MockLightWalletService {
*/
override func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
throw LightWalletServiceError.generalError
throw LightWalletServiceError.invalidBlock
}
}