Merge pull request #1239 from LukasKorba/1238-Report-sync-progress-with-the-new-getScanProgress

[#1238] Report sync progress with the new getScanProgress
This commit is contained in:
Lukas Korba 2023-09-08 15:44:17 +02:00 committed by GitHub
commit db23944415
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 95 additions and 27 deletions

View File

@ -307,7 +307,7 @@ extension SDKSynchronizer {
static func textFor(state: SyncStatus) -> String {
switch state {
case .syncing(let progress):
return "Syncing \(progress)"
return "Syncing \(progress * 100.0)%"
case .upToDate:
return "Up to Date 😎"

View File

@ -10,11 +10,13 @@ import Foundation
final class ScanAction {
let configProvider: CompactBlockProcessor.ConfigProvider
let blockScanner: BlockScanner
let rustBackend: ZcashRustBackendWelding
let logger: Logger
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
self.configProvider = configProvider
blockScanner = container.resolve(BlockScanner.self)
rustBackend = container.resolve(ZcashRustBackendWelding.self)
logger = container.resolve(Logger.self)
}
@ -59,13 +61,19 @@ extension ScanAction: Action {
: totalProgressRange.upperBound
)
let progress = BlockProgress(
startHeight: totalProgressRange.lowerBound,
targetHeight: totalProgressRange.upperBound,
progressHeight: incrementedprocessedHeight
)
self?.logger.debug("progress: \(progress)")
await didUpdate(.progressPartialUpdate(.syncing(progress)))
// report scan progress only if it's available
if let scanProgress = try? await self?.rustBackend.getScanProgress() {
// TODO: [#1240] remove BlockProgress, https://github.com/zcash/ZcashLightClientKit/issues/1240
let progress = BlockProgress(
startHeight: totalProgressRange.lowerBound,
targetHeight: totalProgressRange.upperBound,
progressHeight: incrementedprocessedHeight,
scanProgress: try scanProgress.progress()
)
self?.logger.debug("progress: \(progress)")
await didUpdate(.progressPartialUpdate(.syncing(progress)))
}
// ScanAction is controlled locally so it must report back the updated scanned height
await context.update(lastScannedHeight: lastScannedHeight)

View File

@ -204,7 +204,8 @@ actor BlockDownloaderImpl {
progress: BlockProgress(
startHeight: totalProgressRange.lowerBound,
targetHeight: totalProgressRange.upperBound,
progressHeight: Int(lastDownloadedBlockHeight)
progressHeight: Int(lastDownloadedBlockHeight),
scanProgress: 0
),
start: startTime,
end: finishTime,

View File

@ -138,7 +138,8 @@ extension BlockEnhancerImpl: BlockEnhancer {
progress: BlockProgress(
startHeight: range.lowerBound,
targetHeight: range.upperBound,
progressHeight: range.upperBound
progressHeight: range.upperBound,
scanProgress: 0
),
start: startTime,
end: Date(),

View File

@ -89,7 +89,8 @@ extension UTXOFetcherImpl: UTXOFetcher {
progress: BlockProgress(
startHeight: 0,
targetHeight: 1,
progressHeight: 1
progressHeight: 1,
scanProgress: 0
),
start: startTime,
end: Date(),

View File

@ -17,7 +17,7 @@ protocol BlockScanner {
func scanBlocks(
at range: CompactBlockRange,
totalProgressRange: CompactBlockRange,
didScan: @escaping (BlockHeight, UInt32) async -> Void
didScan: @escaping (BlockHeight, UInt32) async throws -> Void
) async throws -> BlockHeight
}
@ -34,7 +34,7 @@ extension BlockScannerImpl: BlockScanner {
func scanBlocks(
at range: CompactBlockRange,
totalProgressRange: CompactBlockRange,
didScan: @escaping (BlockHeight, UInt32) async -> Void
didScan: @escaping (BlockHeight, UInt32) async throws -> Void
) async throws -> BlockHeight {
logger.debug("Going to scan blocks in range: \(range)")
try Task.checkCancellation()
@ -68,12 +68,13 @@ extension BlockScannerImpl: BlockScanner {
scannedNewBlocks = previousScannedHeight != lastScannedHeight
if scannedNewBlocks {
await didScan(lastScannedHeight, batchSize)
try await didScan(lastScannedHeight, batchSize)
let progress = BlockProgress(
startHeight: totalProgressRange.lowerBound,
targetHeight: totalProgressRange.upperBound,
progressHeight: lastScannedHeight
progressHeight: lastScannedHeight,
scanProgress: 0
)
metrics.pushProgressReport(

View File

@ -41,7 +41,7 @@ final actor CompactBlockProgress {
}
if case let .syncing(progress) = update {
actionProgresses[.scan] = progress.progress
actionProgresses[.scan] = progress.scanProgress
}
return true

View File

@ -11,6 +11,7 @@ public struct BlockProgress: Equatable {
public let startHeight: BlockHeight
public let targetHeight: BlockHeight
public let progressHeight: BlockHeight
public let scanProgress: Float
public var progress: Float {
let overall = self.targetHeight - self.startHeight
@ -20,5 +21,10 @@ public struct BlockProgress: Equatable {
}
public extension BlockProgress {
static let nullProgress = BlockProgress(startHeight: 0, targetHeight: 0, progressHeight: 0)
static let nullProgress = BlockProgress(
startHeight: 0,
targetHeight: 0,
progressHeight: 0,
scanProgress: 0
)
}

View File

@ -3,7 +3,7 @@
scriptDir=${0:a:h}
cd "${scriptDir}"
sourcery_version=2.0.2
sourcery_version=2.0.3
if which sourcery >/dev/null; then
if [[ $(sourcery --version) != $sourcery_version ]]; then

View File

@ -1,4 +1,4 @@
// Generated using Sourcery 2.0.2 https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.0.3 https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
/*
@ -298,7 +298,7 @@ public enum ZcashError: Equatable, Error {
/// sourcery: code="ZRUST0049"
/// ZRUST0049
case rustSuggestScanRanges(_ rustError: String)
/// Invalid transaction ID length when calling ZcashRustBackend.getMemo
/// Invalid transaction ID length when calling ZcashRustBackend.getMemo. txId must be 32 bytes.
/// ZRUST0050
case rustGetMemoInvalidTxIdLength
/// Error from rust layer when calling ZcashRustBackend.getScanProgress
@ -317,6 +317,10 @@ public enum ZcashError: Equatable, Error {
/// - `rustError` contains error generated by the rust layer.
/// ZRUST0054
case rustLatestCachedBlockHeight(_ rustError: String)
/// Rust layer's call ZcashRustBackend.getScanProgress returned values that after computation are outside of allowed range 0-100%.
/// - `progress` value reported
/// ZRUST0055
case rustScanProgressOutOfRange(_ progress: String)
/// SQLite query failed when fetching all accounts from the database.
/// - `sqliteError` is error produced by SQLite library.
/// ZADAO0001
@ -660,11 +664,12 @@ public enum ZcashError: Equatable, Error {
case .rustPutSaplingSubtreeRoots: return "Error from rust layer when calling ZcashRustBackend.putSaplingSubtreeRoots"
case .rustUpdateChainTip: return "Error from rust layer when calling ZcashRustBackend.updateChainTip"
case .rustSuggestScanRanges: return "Error from rust layer when calling ZcashRustBackend.suggestScanRanges"
case .rustGetMemoInvalidTxIdLength: return "txId must be 32 bytes"
case .rustGetMemoInvalidTxIdLength: return "Invalid transaction ID length when calling ZcashRustBackend.getMemo. txId must be 32 bytes."
case .rustGetScanProgress: return "Error from rust layer when calling ZcashRustBackend.getScanProgress"
case .rustFullyScannedHeight: return "Error from rust layer when calling ZcashRustBackend.fullyScannedHeight"
case .rustMaxScannedHeight: return "Error from rust layer when calling ZcashRustBackend.maxScannedHeight"
case .rustLatestCachedBlockHeight: return "Error from rust layer when calling ZcashRustBackend.latestCachedBlockHeight"
case .rustScanProgressOutOfRange: return "Rust layer's call ZcashRustBackend.getScanProgress returned values that after computation are outside of allowed range 0-100%."
case .accountDAOGetAll: return "SQLite query failed when fetching all accounts from the database."
case .accountDAOGetAllCantDecode: return "Fetched accounts from SQLite but can't decode them."
case .accountDAOFindBy: return "SQLite query failed when seaching for accounts in the database."
@ -836,6 +841,7 @@ public enum ZcashError: Equatable, Error {
case .rustFullyScannedHeight: return .rustFullyScannedHeight
case .rustMaxScannedHeight: return .rustMaxScannedHeight
case .rustLatestCachedBlockHeight: return .rustLatestCachedBlockHeight
case .rustScanProgressOutOfRange: return .rustScanProgressOutOfRange
case .accountDAOGetAll: return .accountDAOGetAll
case .accountDAOGetAllCantDecode: return .accountDAOGetAllCantDecode
case .accountDAOFindBy: return .accountDAOFindBy

View File

@ -1,4 +1,4 @@
// Generated using Sourcery 2.0.2 https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.0.3 https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
/*
@ -163,7 +163,7 @@ public enum ZcashErrorCode: String {
case rustUpdateChainTip = "ZRUST0048"
/// Error from rust layer when calling ZcashRustBackend.suggestScanRanges
case rustSuggestScanRanges = "ZRUST0049"
/// Invalid transaction ID length when calling ZcashRustBackend.getMemo
/// Invalid transaction ID length when calling ZcashRustBackend.getMemo. txId must be 32 bytes.
case rustGetMemoInvalidTxIdLength = "ZRUST0050"
/// Error from rust layer when calling ZcashRustBackend.getScanProgress
case rustGetScanProgress = "ZRUST0051"
@ -173,6 +173,8 @@ public enum ZcashErrorCode: String {
case rustMaxScannedHeight = "ZRUST0053"
/// Error from rust layer when calling ZcashRustBackend.latestCachedBlockHeight
case rustLatestCachedBlockHeight = "ZRUST0054"
/// Rust layer's call ZcashRustBackend.getScanProgress returned values that after computation are outside of allowed range 0-100%.
case rustScanProgressOutOfRange = "ZRUST0055"
/// SQLite query failed when fetching all accounts from the database.
case accountDAOGetAll = "ZADAO0001"
/// Fetched accounts from SQLite but can't decode them.

View File

@ -325,6 +325,29 @@ enum ZcashErrorDefinition {
/// - `rustError` contains error generated by the rust layer.
/// sourcery: code="ZRUST0049"
case rustSuggestScanRanges(_ rustError: String)
/// Invalid transaction ID length when calling ZcashRustBackend.getMemo. txId must be 32 bytes.
// sourcery: code="ZRUST0050"
case rustGetMemoInvalidTxIdLength
/// Error from rust layer when calling ZcashRustBackend.getScanProgress
/// - `rustError` contains error generated by the rust layer.
// sourcery: code="ZRUST0051"
case rustGetScanProgress(_ rustError: String)
/// Error from rust layer when calling ZcashRustBackend.fullyScannedHeight
/// - `rustError` contains error generated by the rust layer.
// sourcery: code="ZRUST0052"
case rustFullyScannedHeight(_ rustError: String)
/// Error from rust layer when calling ZcashRustBackend.maxScannedHeight
/// - `rustError` contains error generated by the rust layer.
// sourcery: code="ZRUST0053"
case rustMaxScannedHeight(_ rustError: String)
/// Error from rust layer when calling ZcashRustBackend.latestCachedBlockHeight
/// - `rustError` contains error generated by the rust layer.
// sourcery: code="ZRUST0054"
case rustLatestCachedBlockHeight(_ rustError: String)
/// Rust layer's call ZcashRustBackend.getScanProgress returned values that after computation are outside of allowed range 0-100%.
/// - `progress` value reported
// sourcery: code="ZRUST0055"
case rustScanProgressOutOfRange(_ progress: String)
// MARK: - Account DAO

View File

@ -7,7 +7,18 @@
import Foundation
struct ScanProgress {
struct ScanProgress: Equatable {
let numerator: UInt64
let denominator: UInt64
func progress() throws -> Float {
let value = Float(numerator) / Float(denominator)
// this shouldn't happen but if it does, we need to get notified by clients and work on a fix
if value > 1.0 {
throw ZcashError.rustScanProgressOutOfRange("\(value)")
}
return value
}
}

View File

@ -150,6 +150,14 @@ final class ScanActionTests: ZcashTestCase {
_ blockScannerMock: BlockScannerMock,
_ loggerMock: LoggerMock
) -> ScanAction {
let rustBackendMock = ZcashRustBackendWeldingMock(
consensusBranchIdForHeightClosure: { height in
XCTAssertEqual(height, 2, "")
return -1026109260
}
)
mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in rustBackendMock }
mockContainer.mock(type: BlockScanner.self, isSingleton: true) { _ in blockScannerMock }
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }

View File

@ -528,11 +528,11 @@ class BlockScannerMock: BlockScanner {
var scanBlocksAtTotalProgressRangeDidScanCalled: Bool {
return scanBlocksAtTotalProgressRangeDidScanCallsCount > 0
}
var scanBlocksAtTotalProgressRangeDidScanReceivedArguments: (range: CompactBlockRange, totalProgressRange: CompactBlockRange, didScan: (BlockHeight, UInt32) async -> Void)?
var scanBlocksAtTotalProgressRangeDidScanReceivedArguments: (range: CompactBlockRange, totalProgressRange: CompactBlockRange, didScan: (BlockHeight, UInt32) async throws -> Void)?
var scanBlocksAtTotalProgressRangeDidScanReturnValue: BlockHeight!
var scanBlocksAtTotalProgressRangeDidScanClosure: ((CompactBlockRange, CompactBlockRange, @escaping (BlockHeight, UInt32) async -> Void) async throws -> BlockHeight)?
var scanBlocksAtTotalProgressRangeDidScanClosure: ((CompactBlockRange, CompactBlockRange, @escaping (BlockHeight, UInt32) async throws -> Void) async throws -> BlockHeight)?
func scanBlocks(at range: CompactBlockRange, totalProgressRange: CompactBlockRange, didScan: @escaping (BlockHeight, UInt32) async -> Void) async throws -> BlockHeight {
func scanBlocks(at range: CompactBlockRange, totalProgressRange: CompactBlockRange, didScan: @escaping (BlockHeight, UInt32) async throws -> Void) async throws -> BlockHeight {
if let error = scanBlocksAtTotalProgressRangeDidScanThrowableError {
throw error
}