Merge pull request #618 from Chlup/488_delete_cache

[#488] Delete cache db when sync ends
This commit is contained in:
Francisco Gindre 2022-11-17 08:24:53 -03:00 committed by GitHub
commit 667bda24a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 86 additions and 22 deletions

View File

@ -11,6 +11,7 @@ import SQLite
protocol ConnectionProvider {
func connection() throws -> Connection
func close()
}
class CompactBlockStorage: CompactBlockDAO {
@ -29,6 +30,11 @@ class CompactBlockStorage: CompactBlockDAO {
private func dataColumn() -> Expression<Blob> {
Expression<Blob>("data")
}
func closeDBConnection() {
dbProvider.close()
}
func createTable() throws {
do {
let compactBlocks = compactBlocksTable()
@ -91,6 +97,21 @@ extension CompactBlockStorage: CompactBlockRepository {
}
return try await task.value
}
func latestBlock() throws -> ZcashCompactBlock {
let dataColumn = self.dataColumn()
let heightColumn = self.heightColumn()
let query = compactBlocksTable()
.select(dataColumn, heightColumn)
.order(heightColumn.desc)
.limit(1)
guard let blockData = try dbProvider.connection().prepare(query).first(where: { _ in return true }) else {
throw StorageError.latestBlockNotFound
}
return ZcashCompactBlock(height: Int(blockData[heightColumn]), data: Data(blob: blockData[dataColumn]))
}
func write(blocks: [ZcashCompactBlock]) async throws {
let task = Task(priority: .userInitiated) {

View File

@ -17,6 +17,7 @@ enum StorageError: Error {
case malformedEntity(fields: [String]?)
case transactionFailed(underlyingError: Error)
case invalidMigrationVersion(version: Int32)
case latestBlockNotFound
case migrationFailed(underlyingError: Error)
case migrationFailedWithMessage(message: String)
}

View File

@ -70,4 +70,8 @@ class SimpleConnectionProvider: ConnectionProvider {
}
return conn
}
func close() {
self.db = nil
}
}

View File

@ -58,7 +58,7 @@ public protocol CompactBlockDownloading {
Non-blocking
*/
func latestBlockHeightAsync() async throws -> BlockHeight
/**
Gets the transaction for the Id given
- Parameter txId: Data representing the transaction Id

View File

@ -598,11 +598,17 @@ public actor CompactBlockProcessor {
targetHeight: range.upperBound
)
}
try storage.createTable()
try await compactBlockValidation()
try await compactBlockBatchScanning(range: range)
try await compactBlockEnhancement(range: range)
try await fetchUnspentTxOutputs(range: range)
try await removeCacheDB()
} catch {
LoggerProxy.error("Sync failed with error: \(error)")
if !(Task.isCancelled) {
await fail(error)
} else {
@ -841,6 +847,30 @@ public actor CompactBlockProcessor {
userInfo: nil
)
}
private func removeCacheDB() async throws {
let latestBlock: ZcashCompactBlock
do {
latestBlock = try storage.latestBlock()
} catch let error {
// If we don't have anything downloaded we don't need to remove DB and we also don't want to throw error and error out whole sync process.
if let err = error as? StorageError, case .latestBlockNotFound = err {
return
} else {
throw error
}
}
storage.closeDBConnection()
try FileManager.default.removeItem(at: config.cacheDb)
try storage.createTable()
// Latest downloaded block needs to be preserved because after the sync process is interrupted it must be correctly resumed. And for that
// we need correct information which was downloaded as latest.
try await storage.write(blocks: [latestBlock])
LoggerProxy.info("Cache removed")
}
private func setTimer() async {
let interval = self.config.blockPollInterval
@ -1142,8 +1172,6 @@ extension CompactBlockProcessor {
)
let lastDownloadedBlockHeight = try downloader.lastDownloadedBlockHeight()
let lastScannedHeight = try transactionRepository.lastScannedHeight()
let latestBlockheight = try service.latestBlockHeight()
// Syncing process can be interrupted in any phase. And here it must be detected in which phase is syncing process.
@ -1153,7 +1181,7 @@ extension CompactBlockProcessor {
latestDownloadedBlockHeight = max(config.walletBirthday, lastDownloadedBlockHeight)
} else {
// Here all the blocks are downloaded and last scan height should be then used to compute processing range.
latestDownloadedBlockHeight = max(config.walletBirthday, lastScannedHeight)
latestDownloadedBlockHeight = max(config.walletBirthday, try transactionRepository.lastScannedHeight())
}

View File

@ -9,6 +9,8 @@
import Foundation
protocol CompactBlockDAO {
func closeDBConnection()
func createTable() throws
func insert(_ block: ZcashCompactBlock) throws

View File

@ -20,9 +20,8 @@ extension ZcashCompactBlock: Encodable { }
protocol CompactBlockRepository {
/**
Gets the highest block that is currently stored.
Gets the height of the highest block that is currently stored.
*/
func latestHeight() throws -> BlockHeight
/**
@ -31,6 +30,11 @@ protocol CompactBlockRepository {
*/
func latestHeightAsync() async throws -> BlockHeight
/**
Gets the block with the highest height that is currently stored.
*/
func latestBlock() throws -> ZcashCompactBlock
/**
Write the given blocks to this store, which may be anything from an in-memory cache to a DB.
Non-Blocking

View File

@ -153,11 +153,7 @@ public protocol Synchronizer {
/// - from: the confirmed transaction from which the query should start from or nil to retrieve from the most recent transaction
/// - limit: the maximum amount of items this should return if available
/// - Returns: an array with the given Transactions or nil
func allConfirmedTransactions(from transaction: ConfirmedTransactionEntity?, limit: Int) throws -> [ConfirmedTransactionEntity]?
/// Returns the latest downloaded height from the compact block cache
func latestDownloadedHeight() async throws -> BlockHeight
func allConfirmedTransactions(from transaction: ConfirmedTransactionEntity?, limit: Int) throws -> [ConfirmedTransactionEntity]?
/// Returns the latest block height from the provided Lightwallet endpoint
func latestHeight(result: @escaping (Result<BlockHeight, Error>) -> Void)

View File

@ -569,10 +569,6 @@ public class SDKSynchronizer: Synchronizer {
PagedTransactionRepositoryBuilder.build(initializer: initializer, kind: .all)
}
public func latestDownloadedHeight() async throws -> BlockHeight {
try await blockProcessor.downloader.lastDownloadedBlockHeight()
}
public func latestHeight(result: @escaping (Result<BlockHeight, Error>) -> Void) {
Task {
do {

View File

@ -1308,8 +1308,8 @@ class AdvancedReOrgTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 500)
let latestDownloadedHeight = try await coordinator.synchronizer.latestDownloadedHeight()
XCTAssertEqual(latestDownloadedHeight, birthday + fullSyncLength)
let latestScannedHeight = coordinator.synchronizer.latestScannedHeight
XCTAssertEqual(latestScannedHeight, birthday + fullSyncLength)
}
func handleError(_ error: Error?) {

View File

@ -25,7 +25,11 @@ class ZcashConsoleFakeStorage: CompactBlockRepository {
func latestHeight() throws -> Int {
return self.latestBlockHeight
}
func latestBlock() throws -> ZcashLightClientKit.ZcashCompactBlock {
return ZcashCompactBlock(height: latestBlockHeight, data: Data())
}
func rewind(to height: BlockHeight) throws {
fakeRewind(to: height)
}

View File

@ -116,17 +116,25 @@ class TestDbBuilder {
}
}
struct InMemoryDbProvider: ConnectionProvider {
class InMemoryDbProvider: ConnectionProvider {
var readonly: Bool
var conn: Connection
var conn: Connection?
init(readonly: Bool = false) throws {
self.readonly = readonly
self.conn = try Connection(.inMemory, readonly: readonly)
}
func connection() throws -> Connection {
self.conn
guard let conn else {
let newConnection = try Connection(.inMemory, readonly: readonly)
self.conn = newConnection
return newConnection
}
return conn
}
func close() {
self.conn = nil
}
}