ZcashLightClientKit/Sources/ZcashLightClientKit/Block/Processor/CompactBlockScanning.swift

199 lines
8.0 KiB
Swift
Raw Normal View History

[476] CompactBlockProcessor to async/await - getting rid of the Operation Queue - the cleanup is needed - the update of tests is needed - tested and it successfully finishes the sync process [476] CompactBlockProcessor to async/await - old processNewBlocks() removed [476] CompactBlockProcessor to async/await - unused operations removed [476] CompactBlockProcessor to async/await - unit tests update [476] CompactBlockProcessor to async/await - unit tests refactored [476] CompactBlockProcessor to async/await - cleanup of deprecated method [476] CompactBlockProcessor to async/await - fail(error) was called even for canceled tasks but that must be excluded [476] CompactBlockProcessor to async/await - removal of all ZcashOperations from the code (unit test will follow) [476] CompactBlockProcessor to async/await - network tests in building and success order again [476] CompactBlockProcessor to async/await - offline tests in building and success order [476] CompactBlockProcessor to async/await (519) - cleanup of suspending the task [476] CompactBlockProcessor to async/await (519) - most comments resolved [476] CompactBlockProcessor to async/await (519) - thread safe state for both sync and async context [476] CompactBlockProcessor to async/await (519) - fixed build for a sample project [476] CompactBlockProcessor to async/await (519) - func testStartNotifiesSuscriptors() reverted [476] CompactBlockProcessor to async/await (519) - TODO added to track why we used NSLock instead of an Actor - Task priority enhanced [476] CompactBlockProcessor to async/await (519) - cleanup in Tasks and priorities
2022-09-01 05:58:41 -07:00
//
// CompactBlockProcessing.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 10/15/19.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
extension CompactBlockProcessor {
func compactBlockBatchScanning(range: CompactBlockRange) async throws {
try Task.checkCancellation()
state = .scanning
// TODO: remove this arbitrary batch size https://github.com/zcash/ZcashLightClientKit/issues/576
let batchSize = scanBatchSize(for: range, network: self.config.network.networkType)
[476] CompactBlockProcessor to async/await - getting rid of the Operation Queue - the cleanup is needed - the update of tests is needed - tested and it successfully finishes the sync process [476] CompactBlockProcessor to async/await - old processNewBlocks() removed [476] CompactBlockProcessor to async/await - unused operations removed [476] CompactBlockProcessor to async/await - unit tests update [476] CompactBlockProcessor to async/await - unit tests refactored [476] CompactBlockProcessor to async/await - cleanup of deprecated method [476] CompactBlockProcessor to async/await - fail(error) was called even for canceled tasks but that must be excluded [476] CompactBlockProcessor to async/await - removal of all ZcashOperations from the code (unit test will follow) [476] CompactBlockProcessor to async/await - network tests in building and success order again [476] CompactBlockProcessor to async/await - offline tests in building and success order [476] CompactBlockProcessor to async/await (519) - cleanup of suspending the task [476] CompactBlockProcessor to async/await (519) - most comments resolved [476] CompactBlockProcessor to async/await (519) - thread safe state for both sync and async context [476] CompactBlockProcessor to async/await (519) - fixed build for a sample project [476] CompactBlockProcessor to async/await (519) - func testStartNotifiesSuscriptors() reverted [476] CompactBlockProcessor to async/await (519) - TODO added to track why we used NSLock instead of an Actor - Task priority enhanced [476] CompactBlockProcessor to async/await (519) - cleanup in Tasks and priorities
2022-09-01 05:58:41 -07:00
do {
if batchSize == 0 {
let scanStartTime = Date()
guard self.rustBackend.scanBlocks(dbCache: config.cacheDb, dbData: config.dataDb, limit: batchSize, networkType: config.network.networkType) else {
let error: Error = rustBackend.lastError() ?? CompactBlockProcessorError.unknown
LoggerProxy.debug("block scanning failed with error: \(String(describing: error))")
throw error
}
let scanFinishTime = Date()
NotificationCenter.default.mainThreadPostNotification(
[476] CompactBlockProcessor to async/await - getting rid of the Operation Queue - the cleanup is needed - the update of tests is needed - tested and it successfully finishes the sync process [476] CompactBlockProcessor to async/await - old processNewBlocks() removed [476] CompactBlockProcessor to async/await - unused operations removed [476] CompactBlockProcessor to async/await - unit tests update [476] CompactBlockProcessor to async/await - unit tests refactored [476] CompactBlockProcessor to async/await - cleanup of deprecated method [476] CompactBlockProcessor to async/await - fail(error) was called even for canceled tasks but that must be excluded [476] CompactBlockProcessor to async/await - removal of all ZcashOperations from the code (unit test will follow) [476] CompactBlockProcessor to async/await - network tests in building and success order again [476] CompactBlockProcessor to async/await - offline tests in building and success order [476] CompactBlockProcessor to async/await (519) - cleanup of suspending the task [476] CompactBlockProcessor to async/await (519) - most comments resolved [476] CompactBlockProcessor to async/await (519) - thread safe state for both sync and async context [476] CompactBlockProcessor to async/await (519) - fixed build for a sample project [476] CompactBlockProcessor to async/await (519) - func testStartNotifiesSuscriptors() reverted [476] CompactBlockProcessor to async/await (519) - TODO added to track why we used NSLock instead of an Actor - Task priority enhanced [476] CompactBlockProcessor to async/await (519) - cleanup in Tasks and priorities
2022-09-01 05:58:41 -07:00
SDKMetrics.progressReportNotification(
progress: BlockProgress(
startHeight: range.lowerBound,
targetHeight: range.upperBound,
progressHeight: range.upperBound
),
start: scanStartTime,
end: scanFinishTime,
task: .scanBlocks
)
)
let seconds = scanFinishTime.timeIntervalSinceReferenceDate - scanStartTime.timeIntervalSinceReferenceDate
LoggerProxy.debug("Scanned \(range.count) blocks in \(seconds) seconds")
} else {
let scanStartHeight = try transactionRepository.lastScannedHeight()
let targetScanHeight = range.upperBound
var scannedNewBlocks = false
var lastScannedHeight = scanStartHeight
repeat {
try Task.checkCancellation()
let previousScannedHeight = lastScannedHeight
let scanStartTime = Date()
guard self.rustBackend.scanBlocks(
dbCache: config.cacheDb,
dbData: config.dataDb,
limit: batchSize,
networkType: config.network.networkType
) else {
let error: Error = rustBackend.lastError() ?? CompactBlockProcessorError.unknown
LoggerProxy.debug("block scanning failed with error: \(String(describing: error))")
throw error
}
let scanFinishTime = Date()
lastScannedHeight = try transactionRepository.lastScannedHeight()
scannedNewBlocks = previousScannedHeight != lastScannedHeight
if scannedNewBlocks {
let progress = BlockProgress(startHeight: scanStartHeight, targetHeight: targetScanHeight, progressHeight: lastScannedHeight)
notifyProgress(.scan(progress))
NotificationCenter.default.mainThreadPostNotification(
[476] CompactBlockProcessor to async/await - getting rid of the Operation Queue - the cleanup is needed - the update of tests is needed - tested and it successfully finishes the sync process [476] CompactBlockProcessor to async/await - old processNewBlocks() removed [476] CompactBlockProcessor to async/await - unused operations removed [476] CompactBlockProcessor to async/await - unit tests update [476] CompactBlockProcessor to async/await - unit tests refactored [476] CompactBlockProcessor to async/await - cleanup of deprecated method [476] CompactBlockProcessor to async/await - fail(error) was called even for canceled tasks but that must be excluded [476] CompactBlockProcessor to async/await - removal of all ZcashOperations from the code (unit test will follow) [476] CompactBlockProcessor to async/await - network tests in building and success order again [476] CompactBlockProcessor to async/await - offline tests in building and success order [476] CompactBlockProcessor to async/await (519) - cleanup of suspending the task [476] CompactBlockProcessor to async/await (519) - most comments resolved [476] CompactBlockProcessor to async/await (519) - thread safe state for both sync and async context [476] CompactBlockProcessor to async/await (519) - fixed build for a sample project [476] CompactBlockProcessor to async/await (519) - func testStartNotifiesSuscriptors() reverted [476] CompactBlockProcessor to async/await (519) - TODO added to track why we used NSLock instead of an Actor - Task priority enhanced [476] CompactBlockProcessor to async/await (519) - cleanup in Tasks and priorities
2022-09-01 05:58:41 -07:00
SDKMetrics.progressReportNotification(
progress: progress,
start: scanStartTime,
end: scanFinishTime,
task: .scanBlocks
)
)
let heightCount = lastScannedHeight - previousScannedHeight
let seconds = scanFinishTime.timeIntervalSinceReferenceDate - scanStartTime.timeIntervalSinceReferenceDate
LoggerProxy.debug("Scanned \(heightCount) blocks in \(seconds) seconds")
}
await Task.yield()
[476] CompactBlockProcessor to async/await - getting rid of the Operation Queue - the cleanup is needed - the update of tests is needed - tested and it successfully finishes the sync process [476] CompactBlockProcessor to async/await - old processNewBlocks() removed [476] CompactBlockProcessor to async/await - unused operations removed [476] CompactBlockProcessor to async/await - unit tests update [476] CompactBlockProcessor to async/await - unit tests refactored [476] CompactBlockProcessor to async/await - cleanup of deprecated method [476] CompactBlockProcessor to async/await - fail(error) was called even for canceled tasks but that must be excluded [476] CompactBlockProcessor to async/await - removal of all ZcashOperations from the code (unit test will follow) [476] CompactBlockProcessor to async/await - network tests in building and success order again [476] CompactBlockProcessor to async/await - offline tests in building and success order [476] CompactBlockProcessor to async/await (519) - cleanup of suspending the task [476] CompactBlockProcessor to async/await (519) - most comments resolved [476] CompactBlockProcessor to async/await (519) - thread safe state for both sync and async context [476] CompactBlockProcessor to async/await (519) - fixed build for a sample project [476] CompactBlockProcessor to async/await (519) - func testStartNotifiesSuscriptors() reverted [476] CompactBlockProcessor to async/await (519) - TODO added to track why we used NSLock instead of an Actor - Task priority enhanced [476] CompactBlockProcessor to async/await (519) - cleanup in Tasks and priorities
2022-09-01 05:58:41 -07:00
} while !Task.isCancelled && scannedNewBlocks && lastScannedHeight < targetScanHeight
if Task.isCancelled {
state = .stopped
[476] CompactBlockProcessor to async/await - getting rid of the Operation Queue - the cleanup is needed - the update of tests is needed - tested and it successfully finishes the sync process [476] CompactBlockProcessor to async/await - old processNewBlocks() removed [476] CompactBlockProcessor to async/await - unused operations removed [476] CompactBlockProcessor to async/await - unit tests update [476] CompactBlockProcessor to async/await - unit tests refactored [476] CompactBlockProcessor to async/await - cleanup of deprecated method [476] CompactBlockProcessor to async/await - fail(error) was called even for canceled tasks but that must be excluded [476] CompactBlockProcessor to async/await - removal of all ZcashOperations from the code (unit test will follow) [476] CompactBlockProcessor to async/await - network tests in building and success order again [476] CompactBlockProcessor to async/await - offline tests in building and success order [476] CompactBlockProcessor to async/await (519) - cleanup of suspending the task [476] CompactBlockProcessor to async/await (519) - most comments resolved [476] CompactBlockProcessor to async/await (519) - thread safe state for both sync and async context [476] CompactBlockProcessor to async/await (519) - fixed build for a sample project [476] CompactBlockProcessor to async/await (519) - func testStartNotifiesSuscriptors() reverted [476] CompactBlockProcessor to async/await (519) - TODO added to track why we used NSLock instead of an Actor - Task priority enhanced [476] CompactBlockProcessor to async/await (519) - cleanup in Tasks and priorities
2022-09-01 05:58:41 -07:00
LoggerProxy.debug("Warning: compactBlockBatchScanning cancelled")
}
}
} catch {
LoggerProxy.debug("block scanning failed with error: \(String(describing: error))")
throw error
}
}
fileprivate func scanBatchSize(for range: CompactBlockRange, network: NetworkType) -> UInt32 {
guard network == .mainnet else {
return UInt32(config.scanningBatchSize)
}
if range.lowerBound > 1_600_000 {
return 5
}
return UInt32(config.scanningBatchSize)
}
[476] CompactBlockProcessor to async/await - getting rid of the Operation Queue - the cleanup is needed - the update of tests is needed - tested and it successfully finishes the sync process [476] CompactBlockProcessor to async/await - old processNewBlocks() removed [476] CompactBlockProcessor to async/await - unused operations removed [476] CompactBlockProcessor to async/await - unit tests update [476] CompactBlockProcessor to async/await - unit tests refactored [476] CompactBlockProcessor to async/await - cleanup of deprecated method [476] CompactBlockProcessor to async/await - fail(error) was called even for canceled tasks but that must be excluded [476] CompactBlockProcessor to async/await - removal of all ZcashOperations from the code (unit test will follow) [476] CompactBlockProcessor to async/await - network tests in building and success order again [476] CompactBlockProcessor to async/await - offline tests in building and success order [476] CompactBlockProcessor to async/await (519) - cleanup of suspending the task [476] CompactBlockProcessor to async/await (519) - most comments resolved [476] CompactBlockProcessor to async/await (519) - thread safe state for both sync and async context [476] CompactBlockProcessor to async/await (519) - fixed build for a sample project [476] CompactBlockProcessor to async/await (519) - func testStartNotifiesSuscriptors() reverted [476] CompactBlockProcessor to async/await (519) - TODO added to track why we used NSLock instead of an Actor - Task priority enhanced [476] CompactBlockProcessor to async/await (519) - cleanup in Tasks and priorities
2022-09-01 05:58:41 -07:00
}
extension CompactBlockProcessor {
func compactBlockScanning(
rustWelding: ZcashRustBackendWelding.Type,
cacheDb: URL,
dataDb: URL,
limit: UInt32 = 0,
networkType: NetworkType
) throws {
try Task.checkCancellation()
guard rustBackend.scanBlocks(dbCache: cacheDb, dbData: dataDb, limit: limit, networkType: networkType) else {
let error: Error = rustBackend.lastError() ?? CompactBlockProcessorError.unknown
LoggerProxy.debug("block scanning failed with error: \(String(describing: error))")
throw error
}
}
}
public enum SDKMetrics {
struct BlockMetricReport {
var startHeight: BlockHeight
var targetHeight: BlockHeight
var duration: TimeInterval
var task: TaskReported
}
enum TaskReported: String {
case scanBlocks
}
static let startBlockHeightKey = "SDKMetrics.startBlockHeightKey"
static let targetBlockHeightKey = "SDKMetrics.targetBlockHeightKey"
static let progressHeightKey = "SDKMetrics.progressHeight"
static let startDateKey = "SDKMetrics.startDateKey"
static let endDateKey = "SDKMetrics.endDateKey"
static let taskReportedKey = "SDKMetrics.taskReported"
static let notificationName = Notification.Name("SDKMetrics.Notification")
static func blockReportFromNotification(_ notification: Notification) -> BlockMetricReport? {
guard
notification.name == notificationName,
let info = notification.userInfo,
let startHeight = info[startBlockHeightKey] as? BlockHeight,
let targetHeight = info[targetBlockHeightKey] as? BlockHeight,
let task = info[taskReportedKey] as? TaskReported,
let startDate = info[startDateKey] as? Date,
let endDate = info[endDateKey] as? Date
else {
return nil
}
return BlockMetricReport(
startHeight: startHeight,
targetHeight: targetHeight,
duration: abs(
startDate.timeIntervalSinceReferenceDate - endDate.timeIntervalSinceReferenceDate
),
task: task
)
}
static func progressReportNotification(
progress: BlockProgress,
start: Date,
end: Date,
task: SDKMetrics.TaskReported
) -> Notification {
var notification = Notification(name: notificationName)
notification.userInfo = [
startBlockHeightKey: progress.startHeight,
targetBlockHeightKey: progress.targetHeight,
progressHeightKey: progress.progressHeight,
startDateKey: start,
endDateKey: end,
taskReportedKey: task
]
return notification
}
}
extension String.StringInterpolation {
mutating func appendInterpolation(_ value: SDKMetrics.BlockMetricReport) {
let literal = "\(value.task) - \(abs(value.startHeight - value.targetHeight)) processed on \(value.duration) seconds"
appendLiteral(literal)
}
}