Skip to content

Commit 0d22ad6

Browse files
ovitrifclaude
andcommitted
fix: prevent concurrent vss setup calls
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent b3b7e5a commit 0d22ad6

1 file changed

Lines changed: 37 additions & 32 deletions

File tree

app/src/main/java/to/bitkit/data/backup/VssBackupClient.kt

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import com.synonym.vssclient.vssStore
1111
import kotlinx.coroutines.CompletableDeferred
1212
import kotlinx.coroutines.CoroutineDispatcher
1313
import kotlinx.coroutines.delay
14+
import kotlinx.coroutines.sync.Mutex
15+
import kotlinx.coroutines.sync.withLock
1416
import kotlinx.coroutines.withContext
1517
import kotlinx.coroutines.withTimeout
1618
import to.bitkit.data.keychain.Keychain
@@ -30,45 +32,48 @@ class VssBackupClient @Inject constructor(
3032
private val keychain: Keychain,
3133
) {
3234
private var isSetup = CompletableDeferred<Unit>()
35+
private val setupMutex = Mutex()
3336

3437
suspend fun setup(walletIndex: Int = 0): Result<Unit> = withContext(ioDispatcher) {
35-
runCatching {
36-
if (isSetup.isCompleted && !isSetup.isCancelled) {
37-
runCatching { isSetup.await() }.onSuccess { return@runCatching }
38-
}
38+
setupMutex.withLock {
39+
runCatching {
40+
if (isSetup.isCompleted && !isSetup.isCancelled) {
41+
runCatching { isSetup.await() }.onSuccess { return@runCatching }
42+
}
3943

40-
val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name)
41-
?: throw MnemonicNotAvailableException()
44+
val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name)
45+
?: throw MnemonicNotAvailableException()
4246

43-
withTimeout(30.seconds) {
44-
Logger.debug("VSS client setting up…", context = TAG)
45-
val vssUrl = Env.vssServerUrl
46-
val lnurlAuthServerUrl = Env.lnurlAuthServerUrl
47-
val vssStoreId = vssStoreIdProvider.getVssStoreId(walletIndex)
48-
Logger.verbose("Building VSS client with vssUrl: '$vssUrl'", context = TAG)
49-
Logger.verbose("Building VSS client with lnurlAuthServerUrl: '$lnurlAuthServerUrl'", context = TAG)
50-
if (lnurlAuthServerUrl.isNotEmpty()) {
51-
val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name)
47+
withTimeout(30.seconds) {
48+
Logger.debug("VSS client setting up…", context = TAG)
49+
val vssUrl = Env.vssServerUrl
50+
val lnurlAuthServerUrl = Env.lnurlAuthServerUrl
51+
val vssStoreId = vssStoreIdProvider.getVssStoreId(walletIndex)
52+
Logger.verbose("Building VSS client with vssUrl: '$vssUrl'", context = TAG)
53+
Logger.verbose("Building VSS client with lnurlAuthServerUrl: '$lnurlAuthServerUrl'", context = TAG)
54+
if (lnurlAuthServerUrl.isNotEmpty()) {
55+
val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name)
5256

53-
vssNewClientWithLnurlAuth(
54-
baseUrl = vssUrl,
55-
storeId = vssStoreId,
56-
mnemonic = mnemonic,
57-
passphrase = passphrase,
58-
lnurlAuthServerUrl = lnurlAuthServerUrl,
59-
)
60-
} else {
61-
vssNewClient(
62-
baseUrl = vssUrl,
63-
storeId = vssStoreId,
64-
)
57+
vssNewClientWithLnurlAuth(
58+
baseUrl = vssUrl,
59+
storeId = vssStoreId,
60+
mnemonic = mnemonic,
61+
passphrase = passphrase,
62+
lnurlAuthServerUrl = lnurlAuthServerUrl,
63+
)
64+
} else {
65+
vssNewClient(
66+
baseUrl = vssUrl,
67+
storeId = vssStoreId,
68+
)
69+
}
70+
isSetup.complete(Unit)
71+
Logger.info("VSS client setup with server: '$vssUrl'", context = TAG)
6572
}
66-
isSetup.complete(Unit)
67-
Logger.info("VSS client setup with server: '$vssUrl'", context = TAG)
73+
}.onFailure {
74+
isSetup.completeExceptionally(it)
75+
Logger.error("VSS client setup error", it, context = TAG)
6876
}
69-
}.onFailure {
70-
isSetup.completeExceptionally(it)
71-
Logger.error("VSS client setup error", it, context = TAG)
7277
}
7378
}
7479

0 commit comments

Comments
 (0)