From fc7cead1f6461de95874875393391fc14a1a0b17 Mon Sep 17 00:00:00 2001 From: Kevin Gorham Date: Fri, 7 May 2021 03:56:26 -0400 Subject: [PATCH] New: Add the concept of 'prepare'. begin adding a step between the creation of a Synchronizer and starting it, called 'prepare' which is responsible for migrations and other steps to get the data ready for syncing. --- .../java/cash/z/ecc/android/sdk/SdkSynchronizer.kt | 7 +++++++ .../java/cash/z/ecc/android/sdk/Synchronizer.kt | 14 ++++++++++++++ .../cash/z/ecc/android/sdk/exception/Exceptions.kt | 5 +++++ .../sdk/transaction/TransactionRepository.kt | 2 ++ 4 files changed, 28 insertions(+) diff --git a/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt b/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt index d9241a35..565667cf 100644 --- a/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt +++ b/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt @@ -233,6 +233,10 @@ class SdkSynchronizer internal constructor( override val latestBirthdayHeight: Int get() = processor.birthdayHeight + override fun prepare(): Synchronizer = apply { + storage.prepare() + } + /** * Starts this synchronizer within the given scope. For simplicity, attempting to start an * instance that has already been started will throw a [SynchronizerException.FalseStart] @@ -362,6 +366,9 @@ class SdkSynchronizer internal constructor( } private fun CoroutineScope.onReady() = launch(CoroutineExceptionHandler(::onCriticalError)) { + twig("Preparing to start...") + prepare() + twig("Synchronizer (${this@SdkSynchronizer}) Ready. Starting processor!") var lastScanTime = 0L processor.onProcessorErrorListener = ::onProcessorError diff --git a/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt b/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt index dea4d88a..b27c5972 100644 --- a/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt +++ b/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt @@ -30,6 +30,13 @@ interface Synchronizer { */ var isStarted: Boolean + /** + * Prepare the synchronizer to start. Must be called before start. This gives a clear point + * where setup and maintenance can occur for various Synchronizers. One that uses a database + * would take this opportunity to do data migrations or key migrations. + */ + fun prepare(): Synchronizer + /** * Starts this synchronizer within the given scope. * @@ -358,6 +365,13 @@ interface Synchronizer { */ DISCONNECTED, + /** + * 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. + */ + PREPARING, + /** * Indicates that this Synchronizer is actively downloading new blocks from the server. */ diff --git a/src/main/java/cash/z/ecc/android/sdk/exception/Exceptions.kt b/src/main/java/cash/z/ecc/android/sdk/exception/Exceptions.kt index 9e34cb37..35263599 100644 --- a/src/main/java/cash/z/ecc/android/sdk/exception/Exceptions.kt +++ b/src/main/java/cash/z/ecc/android/sdk/exception/Exceptions.kt @@ -32,6 +32,11 @@ sealed class RepositoryException(message: String, cause: Throwable? = null) : Sd "The channel is closed. Note that once a repository has stopped it " + "cannot be restarted. Verify that the repository is not being restarted." ) + object Unprepared : RepositoryException( + "Unprepared repository: Data cannot be accessed before the repository is prepared." + + " Ensure that things have been properly initialized. In most cases, this involves" + + " calling 'synchronizer.prepare' before 'synchronizer.start'" + ) } /** diff --git a/src/main/java/cash/z/ecc/android/sdk/transaction/TransactionRepository.kt b/src/main/java/cash/z/ecc/android/sdk/transaction/TransactionRepository.kt index 14d6807b..13081628 100644 --- a/src/main/java/cash/z/ecc/android/sdk/transaction/TransactionRepository.kt +++ b/src/main/java/cash/z/ecc/android/sdk/transaction/TransactionRepository.kt @@ -88,6 +88,8 @@ interface TransactionRepository { suspend fun getAccountCount(): Int + fun prepare() + // // Transactions //