Skip to content

Commit

Permalink
[#1470] Add APIs to provide clearing of SDK data
Browse files Browse the repository at this point in the history
- Closes #1470
- Changelog update
  • Loading branch information
HonzaR committed Apr 30, 2024
1 parent 9094e6e commit 11a4860
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 5 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- `SdkSynchronizer.closeFlow()` is a Flow-providing version of `Synchronizer.close()`. It safely closes the
Synchronizer together with the related components.
- `WalletCoordinator.deleteSdkDataFlow` is a Flow-providing function that deletes all the persisted data in the SDK
(databases associated with the wallet, all compact blocks, and data derived from those blocks) but preserves the
wallet secrets.

## [2.1.1] - 2024-04-23

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,32 @@ class WalletCoordinator(
}
}

/**
* This Flow-providing function deletes all the persisted data in the SDK (databases associated with this wallet,
* all compact blocks, and data derived from those blocks) but preserves the wallet secrets. This function
* requires secrets available on the device at the time of running.
*/
fun deleteSdkDataFlow(): Flow<Boolean> =
callbackFlow {
walletScope.launch {
val zcashNetwork = persistableWallet.first()?.network
if (null != zcashNetwork) {
synchronizerMutex.withLock {
val didDelete =
Synchronizer.erase(
appContext = applicationContext,
network = zcashNetwork
)
Twig.info { "SDK erase result: $didDelete" }
trySend(didDelete)
}
}
}
awaitClose {
// Nothing to close here
}
}

// Allows for extension functions
companion object
}
33 changes: 32 additions & 1 deletion sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
Expand Down Expand Up @@ -298,7 +300,7 @@ class SdkSynchronizer private constructor(

val shutdownJob =
coroutineScope.launch {
Twig.debug { "Stopping synchronizer $synchronizerKey" }
Twig.info { "Stopping synchronizer $synchronizerKey" }
processor.stop()
}

Expand All @@ -313,6 +315,35 @@ class SdkSynchronizer private constructor(
}
}

/**
* A Flow-providing version of [close] function. This safely closes the Synchronizer together with the related
* components.
*/
fun closeFlow(): Flow<Unit> =
callbackFlow {
val shutdownJob =
coroutineScope.launch {
Twig.info { "Stopping synchronizer $synchronizerKey" }
processor.stop()
}

instances[synchronizerKey] = InstanceState.ShuttingDown(shutdownJob)

shutdownJob.invokeOnCompletion {
coroutineScope.cancel()
_status.value = STOPPED
Twig.info { "Synchronizer $synchronizerKey stopped" }

instances.remove(synchronizerKey)

trySend(Unit)
}

awaitClose {
// Nothing to close here
}
}

override suspend fun getNearestRewindHeight(height: BlockHeight): BlockHeight =
processor.getNearestRewindHeight(
height
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ internal class DatabaseCoordinator private constructor(context: Context) {

val cacheDeleted = fsBlockDbRoot(network, alias).deleteRecursivelySuspend()

Twig.info { "Delete databases result: ${dataDeleted || cacheDeleted}" }

return dataDeleted || cacheDeleted
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@ internal class DbDerivedDataRepository(
override suspend fun close() {
derivedDataDb.close()
}

override suspend fun isClosed(): Boolean {
return derivedDataDb.isClosed()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package cash.z.ecc.android.sdk.internal.db.derived
import android.content.Context
import androidx.sqlite.db.SupportSQLiteDatabase
import cash.z.ecc.android.sdk.internal.NoBackupContextWrapper
import cash.z.ecc.android.sdk.internal.SdkDispatchers
import cash.z.ecc.android.sdk.internal.Twig
import cash.z.ecc.android.sdk.internal.TypesafeBackend
import cash.z.ecc.android.sdk.internal.db.ReadOnlySupportSqliteOpenHelper
import cash.z.ecc.android.sdk.internal.model.Checkpoint
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.ZcashNetwork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File

Expand All @@ -25,11 +25,15 @@ internal class DerivedDataDb private constructor(

val txOutputsView = TxOutputsView(zcashNetwork, sqliteDatabase)

suspend fun close() {
withContext(Dispatchers.IO) {
suspend fun close() =
withContext(SdkDispatchers.DATABASE_IO) {
sqliteDatabase.close()
}
}

suspend fun isClosed(): Boolean =
withContext(SdkDispatchers.DATABASE_IO) {
!sqliteDatabase.isOpen
}

companion object {
// Database migrations are managed by librustzcash. This is a hard-coded value to ensure that Android's
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,6 @@ internal interface DerivedDataRepository {
fun getRecipients(transactionId: FirstClassByteArray): Flow<TransactionRecipient>

suspend fun close()

suspend fun isClosed(): Boolean
}

0 comments on commit 11a4860

Please sign in to comment.