94 lines
4.2 KiB
Swift
94 lines
4.2 KiB
Swift
//
|
|
// ComputeSyncRangesAction.swift
|
|
//
|
|
//
|
|
// Created by Michal Fousek on 05.05.2023.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
final class ComputeSyncRangesAction {
|
|
let configProvider: CompactBlockProcessor.ConfigProvider
|
|
let downloaderService: BlockDownloaderService
|
|
let internalSyncProgress: InternalSyncProgress
|
|
let latestBlocksDataProvider: LatestBlocksDataProvider
|
|
let logger: Logger
|
|
|
|
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
|
self.configProvider = configProvider
|
|
downloaderService = container.resolve(BlockDownloaderService.self)
|
|
internalSyncProgress = container.resolve(InternalSyncProgress.self)
|
|
latestBlocksDataProvider = container.resolve(LatestBlocksDataProvider.self)
|
|
logger = container.resolve(Logger.self)
|
|
}
|
|
|
|
/// This method analyses what must be done and computes range that should be used to compute reported progress.
|
|
func computeTotalProgressRange(from syncRanges: SyncRanges) -> CompactBlockRange {
|
|
guard syncRanges.downloadRange != nil || syncRanges.scanRange != nil else {
|
|
// In this case we are sure that no downloading or scanning happens so this returned range won't be even used. And it's easier to return
|
|
// this "fake" range than to handle nil.
|
|
return 0...0
|
|
}
|
|
|
|
// Thanks to guard above we can be sure that one of these two ranges is not nil.
|
|
let lowerBound = syncRanges.scanRange?.lowerBound ?? syncRanges.downloadRange?.lowerBound ?? 0
|
|
let upperBound = syncRanges.scanRange?.upperBound ?? syncRanges.downloadRange?.upperBound ?? 0
|
|
|
|
return lowerBound...upperBound
|
|
}
|
|
}
|
|
|
|
extension ComputeSyncRangesAction: Action {
|
|
var removeBlocksCacheWhenFailed: Bool { false }
|
|
|
|
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
|
// call internalSyncProgress and compute sync ranges and store them in context
|
|
// if there is nothing sync just switch to finished state
|
|
|
|
let config = await configProvider.config
|
|
let latestDownloadHeight = try await downloaderService.lastDownloadedBlockHeight()
|
|
|
|
try await internalSyncProgress.migrateIfNeeded(latestDownloadedBlockHeightFromCacheDB: latestDownloadHeight, alias: config.alias)
|
|
|
|
await latestBlocksDataProvider.updateScannedData()
|
|
await latestBlocksDataProvider.updateBlockData()
|
|
|
|
let nextState = try await internalSyncProgress.computeNextState(
|
|
latestBlockHeight: latestBlocksDataProvider.latestBlockHeight,
|
|
latestScannedHeight: latestBlocksDataProvider.latestScannedHeight,
|
|
walletBirthday: config.walletBirthday
|
|
)
|
|
|
|
switch nextState {
|
|
case .finishProcessing:
|
|
await context.update(state: .finished)
|
|
case .processNewBlocks(let ranges):
|
|
let totalProgressRange = computeTotalProgressRange(from: ranges)
|
|
await context.update(totalProgressRange: totalProgressRange)
|
|
await context.update(syncRanges: ranges)
|
|
await context.update(state: .checksBeforeSync)
|
|
|
|
logger.debug("""
|
|
Syncing with ranges:
|
|
download: \(ranges.downloadRange?.lowerBound ?? -1)...\(ranges.downloadRange?.upperBound ?? -1)
|
|
scan: \(ranges.scanRange?.lowerBound ?? -1)...\(ranges.scanRange?.upperBound ?? -1)
|
|
enhance range: \(ranges.enhanceRange?.lowerBound ?? -1)...\(ranges.enhanceRange?.upperBound ?? -1)
|
|
fetchUTXO range: \(ranges.fetchUTXORange?.lowerBound ?? -1)...\(ranges.fetchUTXORange?.upperBound ?? -1)
|
|
total progress range: \(totalProgressRange.lowerBound)...\(totalProgressRange.upperBound)
|
|
""")
|
|
|
|
case let .wait(latestHeight, latestDownloadHeight):
|
|
// Lightwalletd might be syncing
|
|
logger.info(
|
|
"Lightwalletd might be syncing: latest downloaded block height is: \(latestDownloadHeight) " +
|
|
"while latest blockheight is reported at: \(latestHeight)"
|
|
)
|
|
await context.update(state: .finished)
|
|
}
|
|
|
|
return context
|
|
}
|
|
|
|
func stop() async { }
|
|
}
|