Replace Status for SyncStatus
This commit is contained in:
parent
a07fdc52dc
commit
558dbeb1ac
|
@ -90,8 +90,12 @@ struct BlockProgress: BlockProgressReporting {
|
|||
var progressHeight: BlockHeight
|
||||
}
|
||||
|
||||
extension Notification.Name {
|
||||
static let connectionStatusChanged = Notification.Name("LightWalletServiceConnectivityStatusChanged")
|
||||
}
|
||||
|
||||
public class LightWalletGRPCService {
|
||||
|
||||
|
||||
var queue: DispatchQueue
|
||||
let channel: Channel
|
||||
let connectionDelegate: ConnectionStatusManager
|
||||
|
@ -488,5 +492,12 @@ extension LightWalletServiceError {
|
|||
class ConnectionStatusManager: ConnectivityStateDelegate {
|
||||
func connectivityStateDidChange(from oldState: ConnectivityState, to newState: ConnectivityState) {
|
||||
LoggerProxy.event("Connection Changed from \(oldState) to \(newState)")
|
||||
NotificationCenter.default.post(
|
||||
name: .blockProcessorConnectivityStateChanged,
|
||||
object: self,
|
||||
userInfo: [
|
||||
CompactBlockProcessorNotificationKey.currentConnectivityStatus : newState,
|
||||
CompactBlockProcessorNotificationKey.previousConnectivityStatus : oldState
|
||||
])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,32 @@ extension ShieldFundsError: LocalizedError {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Represent the connection state to the lightwalletd server
|
||||
*/
|
||||
public enum ConnectionState {
|
||||
/**
|
||||
not in use
|
||||
*/
|
||||
case idle
|
||||
/**
|
||||
there's a connection being attempted from a non error state
|
||||
*/
|
||||
case connecting
|
||||
/**
|
||||
connection is established, ready to use or in use
|
||||
*/
|
||||
case online
|
||||
/**
|
||||
the connection is being re-established after losing it temporarily
|
||||
*/
|
||||
case reconnecting
|
||||
/**
|
||||
the connection has been closed
|
||||
*/
|
||||
case shutdown
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Primary interface for interacting with the SDK. Defines the contract that specific
|
||||
|
@ -57,17 +83,9 @@ implementations like SdkSynchronizer fulfill.
|
|||
public protocol Synchronizer {
|
||||
|
||||
/**
|
||||
Value representing the Status of this Synchronizer. As the status changes, a new
|
||||
value will be emitted by KVO
|
||||
Value representing the Status of this Synchronizer. As the status changes, it will be also notified
|
||||
*/
|
||||
var status: Status { get }
|
||||
|
||||
/**
|
||||
A flow of progress values, typically corresponding to this Synchronizer downloading blocks.
|
||||
Typically, any non-zero value below 1.0 indicates that progress indicators can be shown and
|
||||
a value of 1.0 signals that progress is complete and any progress indicators can be hidden. KVO Compliant
|
||||
*/
|
||||
var progress: Float { get }
|
||||
var status: SyncStatus { get }
|
||||
|
||||
/**
|
||||
prepares this initializer to operate. Initializes the internal state with the given Extended Viewing Keys and a wallet birthday found in the initializer object
|
||||
|
@ -215,73 +233,65 @@ public protocol Synchronizer {
|
|||
func rewind(_ policy: RewindPolicy) throws
|
||||
}
|
||||
|
||||
/**
|
||||
The Status of the synchronizer
|
||||
*/
|
||||
public enum Status {
|
||||
|
||||
public enum SyncStatus: Equatable {
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is actively preparing to start, which usually involves
|
||||
setting up database tables, migrations or taking other maintenance steps that need to
|
||||
occur after an upgrade.
|
||||
*/
|
||||
case unprepared
|
||||
/**
|
||||
Indicates that [stop] has been called on this Synchronizer and it will no longer be used.
|
||||
*/
|
||||
case stopped
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is disconnected from its lightwalletd server.
|
||||
When set, a UI element may want to turn red.
|
||||
*/
|
||||
case disconnected
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is actively downloading new blocks from the server.
|
||||
*/
|
||||
case downloading
|
||||
|
||||
case downloading(_ status: BlockProgressReporting)
|
||||
/**
|
||||
Indicates that this Synchronizer is actively validating new blocks that were downloaded
|
||||
from the server. Blocks need to be verified before they are scanned. This confirms that
|
||||
each block is chain-sequential, thereby detecting missing blocks and reorgs.
|
||||
*/
|
||||
case validating
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is actively scanning new valid blocks that were downloaded
|
||||
from the server.
|
||||
*/
|
||||
case scanning
|
||||
|
||||
case scanning(_ progress: BlockProgressReporting)
|
||||
/**
|
||||
Indicates that this Synchronizer is actively enhancing newly scanned blocks with
|
||||
additional transaction details, fetched from the server.
|
||||
*/
|
||||
case enhancing
|
||||
|
||||
case enhancing(_ progress: EnhancementProgress)
|
||||
/**
|
||||
fetches the transparent balance and stores it locally
|
||||
*/
|
||||
case fetching
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is fully up to date and ready for all wallet functions.
|
||||
When set, a UI element may want to turn green.
|
||||
*/
|
||||
case synced
|
||||
/**
|
||||
Indicates that [stop] has been called on this Synchronizer and it will no longer be used.
|
||||
*/
|
||||
case stopped
|
||||
/**
|
||||
Indicates that this Synchronizer is disconnected from its lightwalletd server.
|
||||
When set, a UI element may want to turn red.
|
||||
*/
|
||||
case disconnected
|
||||
case error(_ error: Error)
|
||||
|
||||
public var isSyncing: Bool {
|
||||
switch self {
|
||||
case .disconnected, .synced, .synced, .unprepared:
|
||||
return false
|
||||
default:
|
||||
case .downloading, .validating, .scanning, .enhancing, .fetching:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Kind of transactions handled by a Synchronizer
|
||||
*/
|
||||
|
@ -304,3 +314,73 @@ public enum RewindPolicy {
|
|||
case transaction(_ transaction: TransactionEntity)
|
||||
case quick
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
extension SyncStatus {
|
||||
public static func == (lhs: SyncStatus, rhs: SyncStatus) -> Bool {
|
||||
switch lhs {
|
||||
case .unprepared:
|
||||
if case .unprepared = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .disconnected:
|
||||
if case .disconnected = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .downloading:
|
||||
if case .downloading = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .validating:
|
||||
if case .validating = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .scanning:
|
||||
if case .scanning = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .enhancing:
|
||||
if case .enhancing = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .fetching:
|
||||
if case .fetching = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .synced:
|
||||
if case .synced = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .stopped:
|
||||
if case .stopped = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .error:
|
||||
if case .error = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,8 @@ public extension Notification.Name {
|
|||
- Note: query userInfo on NotificationKeys.error for an error
|
||||
*/
|
||||
static let synchronizerFailed = Notification.Name("SDKSynchronizerFailed")
|
||||
|
||||
static let synchronizerConnectionStateChanged = Notification.Name("SynchronizerConnectionStateChanged")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,9 +109,11 @@ public class SDKSynchronizer: Synchronizer {
|
|||
public static let error = "SDKSynchronizer.error"
|
||||
public static let currentStatus = "SDKSynchronizer.currentStatus"
|
||||
public static let nextStatus = "SDKSynchronizer.nextStatus"
|
||||
public static let currentConnectionState = "SDKSynchronizer.currentConnectionState"
|
||||
public static let previousConnectionState = "SDKSynchronizer.previousConnectionState"
|
||||
}
|
||||
|
||||
public private(set) var status: Status {
|
||||
public private(set) var status: SyncStatus {
|
||||
didSet {
|
||||
notify(status: status)
|
||||
}
|
||||
|
@ -140,7 +144,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
|
||||
}
|
||||
|
||||
init(status: Status,
|
||||
init(status: SyncStatus,
|
||||
initializer: Initializer,
|
||||
transactionManager: OutboundTransactionManager,
|
||||
transactionRepository: TransactionRepository,
|
||||
|
@ -187,7 +191,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
assert(true,"warning: synchronizer started when already started") // TODO: remove this assertion sometime in the near future
|
||||
LoggerProxy.debug("warning: synchronizer started when already started")
|
||||
return
|
||||
case .stopped, .synced,.disconnected:
|
||||
case .stopped, .synced,.disconnected, .error:
|
||||
do {
|
||||
try blockProcessor.start(retry: retry)
|
||||
} catch {
|
||||
|
@ -269,9 +273,30 @@ public class SDKSynchronizer: Synchronizer {
|
|||
name: Notification.Name.blockProcessorFoundTransactions,
|
||||
object: processor)
|
||||
|
||||
center.addObserver(self,
|
||||
selector: #selector(connectivityStateChanged(_:)),
|
||||
name: Notification.Name.blockProcessorConnectivityStateChanged,
|
||||
object: processor)
|
||||
}
|
||||
|
||||
// MARK: Block Processor notifications
|
||||
@objc func connectivityStateChanged(_ notification: Notification) {
|
||||
guard let userInfo = notification.userInfo,
|
||||
let previous = userInfo[CompactBlockProcessorNotificationKey.previousConnectivityStatus] as? ConnectivityState,
|
||||
let current = userInfo[CompactBlockProcessorNotificationKey.currentConnectivityStatus] as? ConnectivityState else {
|
||||
LoggerProxy.error("found \(Notification.Name.blockProcessorConnectivityStateChanged) but lacks dictionary information. this is probably a programming error")
|
||||
return
|
||||
}
|
||||
|
||||
NotificationCenter.default.post(
|
||||
name: .synchronizerConnectionStateChanged,
|
||||
object: self,
|
||||
userInfo: [
|
||||
NotificationKeys.previousConnectionState : ConnectionState(previous),
|
||||
NotificationKeys.currentConnectionState : ConnectionState(current)
|
||||
])
|
||||
|
||||
}
|
||||
|
||||
@objc func transactionsFound(_ notification: Notification) {
|
||||
guard let userInfo = notification.userInfo,
|
||||
|
@ -310,41 +335,41 @@ public class SDKSynchronizer: Synchronizer {
|
|||
|
||||
@objc func processorStartedDownloading(_ notification: Notification) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.status = .downloading
|
||||
guard let self = self, self.status != .downloading(NullProgress()) else { return }
|
||||
self.status = .downloading(NullProgress())
|
||||
}
|
||||
}
|
||||
|
||||
@objc func processorStartedValidating(_ notification: Notification) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let self = self, self.status != .validating else { return }
|
||||
self.status = .validating
|
||||
}
|
||||
}
|
||||
|
||||
@objc func processorStartedScanning(_ notification: Notification) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.status = .scanning
|
||||
guard let self = self, self.status != .scanning(NullProgress()) else { return }
|
||||
self.status = .scanning(NullProgress())
|
||||
}
|
||||
}
|
||||
@objc func processorStartedEnhancing(_ notification: Notification) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.status = .enhancing
|
||||
guard let self = self, self.status != .enhancing(NullEnhancementProgress()) else { return }
|
||||
self.status = .enhancing(NullEnhancementProgress())
|
||||
}
|
||||
}
|
||||
|
||||
@objc func processorStartedFetching(_ notification: Notification) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let self = self, self.status != .fetching else { return }
|
||||
self.status = .fetching
|
||||
}
|
||||
}
|
||||
|
||||
@objc func processorStopped(_ notification: Notification) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let self = self, self.status != .stopped else { return }
|
||||
self.status = .stopped
|
||||
}
|
||||
}
|
||||
|
@ -355,10 +380,11 @@ public class SDKSynchronizer: Synchronizer {
|
|||
guard let self = self else { return }
|
||||
if let error = notification.userInfo?[CompactBlockProcessorNotificationKey.error] as? Error {
|
||||
self.notifyFailure(error)
|
||||
self.status = .error(self.mapError(error))
|
||||
} else {
|
||||
self.notifyFailure(CompactBlockProcessorError.generalError(message: "This is strange. processorFailed Call received no error message"))
|
||||
self.status = .error(SynchronizerError.generalError(message: "This is strange. processorFailed Call received no error message"))
|
||||
}
|
||||
self.status = .disconnected
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -619,7 +645,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
NotificationCenter.default.post(name: Notification.Name.synchronizerProgressUpdated, object: self, userInfo: userInfo)
|
||||
}
|
||||
|
||||
private func notifyStatusChange(newValue: Status, oldValue: Status) {
|
||||
private func notifyStatusChange(newValue: SyncStatus, oldValue: SyncStatus) {
|
||||
NotificationCenter.default.post(name: .synchronizerStatusWillUpdate,
|
||||
object: self,
|
||||
userInfo:
|
||||
|
@ -627,7 +653,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
NotificationKeys.nextStatus : newValue ])
|
||||
}
|
||||
|
||||
private func notify(status: Status) {
|
||||
private func notify(status: SyncStatus) {
|
||||
|
||||
switch status {
|
||||
case .disconnected:
|
||||
|
@ -649,6 +675,8 @@ public class SDKSynchronizer: Synchronizer {
|
|||
NotificationCenter.default.post(name: Notification.Name.synchronizerEnhancing, object: self)
|
||||
case .fetching:
|
||||
NotificationCenter.default.post(name: Notification.Name.synchronizerFetching, object: self)
|
||||
case .error(let e):
|
||||
self.notifyFailure(e)
|
||||
}
|
||||
}
|
||||
// MARK: book keeping
|
||||
|
@ -760,3 +788,44 @@ extension SDKSynchronizer {
|
|||
(try? self.allReceivedTransactions()) ?? [ConfirmedTransactionEntity]()
|
||||
}
|
||||
}
|
||||
|
||||
import GRPC
|
||||
extension ConnectionState {
|
||||
init(_ connectivityState: ConnectivityState) {
|
||||
switch connectivityState {
|
||||
case .connecting:
|
||||
self = .connecting
|
||||
case .idle:
|
||||
self = .idle
|
||||
case .ready:
|
||||
self = .online
|
||||
case .shutdown:
|
||||
self = .shutdown
|
||||
case .transientFailure:
|
||||
self = .reconnecting
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fileprivate struct NullEnhancementProgress: EnhancementProgress {
|
||||
var totalTransactions: Int { 0 }
|
||||
var enhancedTransactions: Int { 0 }
|
||||
var lastFoundTransaction: ConfirmedTransactionEntity? { nil }
|
||||
var range: CompactBlockRange { 0 ... 0 }
|
||||
}
|
||||
|
||||
fileprivate struct NullProgress: BlockProgressReporting {
|
||||
var startHeight: BlockHeight {
|
||||
0
|
||||
}
|
||||
|
||||
var targetHeight: BlockHeight {
|
||||
0
|
||||
}
|
||||
|
||||
var progressHeight: BlockHeight {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue