diff --git a/src/main/java/cash/z/ecc/android/sdk/block/CompactBlockDownloader.kt b/src/main/java/cash/z/ecc/android/sdk/block/CompactBlockDownloader.kt index ae601411..665f70c6 100644 --- a/src/main/java/cash/z/ecc/android/sdk/block/CompactBlockDownloader.kt +++ b/src/main/java/cash/z/ecc/android/sdk/block/CompactBlockDownloader.kt @@ -1,5 +1,6 @@ package cash.z.ecc.android.sdk.block // iimport cash.z.ecc.android.sdk.exception.LightWalletException import cash.z.ecc.android.sdk.exception.LightWalletException +import cash.z.ecc.android.sdk.ext.retryUpTo import cash.z.ecc.android.sdk.ext.tryWarn import cash.z.ecc.android.sdk.ext.twig import cash.z.ecc.android.sdk.service.LightWalletService @@ -77,13 +78,17 @@ open class CompactBlockDownloader private constructor(val compactBlockStore: Com } suspend fun getServerInfo(): Service.LightdInfo = withContext(IO) { + lateinit var result: Service.LightdInfo try { - lightWalletService.getServerInfo() + result = lightWalletService.getServerInfo() } catch (e: StatusRuntimeException) { - twig("WARNING: reconnecting to service in response to failure: $e") - lightWalletService.reconnect() - lightWalletService.getServerInfo() + retryUpTo(2) { + twig("WARNING: reconnecting to service in response to failure (retry #${it + 1}): $e") + lightWalletService.reconnect() + result = lightWalletService.getServerInfo() + } } + result } suspend fun changeService( diff --git a/src/main/java/cash/z/ecc/android/sdk/service/LightWalletGrpcService.kt b/src/main/java/cash/z/ecc/android/sdk/service/LightWalletGrpcService.kt index c4c21dd0..38d4a7ce 100644 --- a/src/main/java/cash/z/ecc/android/sdk/service/LightWalletGrpcService.kt +++ b/src/main/java/cash/z/ecc/android/sdk/service/LightWalletGrpcService.kt @@ -11,6 +11,7 @@ import cash.z.wallet.sdk.rpc.CompactTxStreamerGrpc import cash.z.wallet.sdk.rpc.Service import com.google.protobuf.ByteString import io.grpc.Channel +import io.grpc.ConnectivityState import io.grpc.ManagedChannel import io.grpc.android.AndroidChannelBuilder import java.util.concurrent.TimeUnit @@ -66,20 +67,17 @@ class LightWalletGrpcService private constructor( override fun getBlockRange(heightRange: IntRange): List { if (heightRange.isEmpty()) return listOf() - channel.resetConnectBackoff() - return channel.createStub(streamingRequestTimeoutSec) + return requireChannel().createStub(streamingRequestTimeoutSec) .getBlockRange(heightRange.toBlockRange()).toList() } override fun getLatestBlockHeight(): Int { - channel.resetConnectBackoff() - return channel.createStub(singleRequestTimeoutSec) + return requireChannel().createStub(singleRequestTimeoutSec) .getLatestBlock(Service.ChainSpec.newBuilder().build()).height.toInt() } override fun getServerInfo(): Service.LightdInfo { - channel.resetConnectBackoff() - return channel.createStub(singleRequestTimeoutSec) + return requireChannel().createStub(singleRequestTimeoutSec) .getLightdInfo(Service.Empty.newBuilder().build()) } @@ -92,11 +90,10 @@ class LightWalletGrpcService private constructor( ) .build() } - channel.resetConnectBackoff() val request = Service.RawTransaction.newBuilder().setData(ByteString.copyFrom(spendTransaction)) .build() - return channel.createStub().sendTransaction(request) + return requireChannel().createStub().sendTransaction(request) } override fun shutdown() { @@ -107,8 +104,7 @@ class LightWalletGrpcService private constructor( override fun fetchTransaction(txId: ByteArray): Service.RawTransaction? { if (txId.isEmpty()) return null - channel.resetConnectBackoff() - return channel.createStub().getTransaction( + return requireChannel().createStub().getTransaction( Service.TxFilter.newBuilder().setHash(ByteString.copyFrom(txId)).build() ) } @@ -117,8 +113,7 @@ class LightWalletGrpcService private constructor( tAddress: String, startHeight: Int ): List { - channel.resetConnectBackoff() - val result = channel.createStub().getAddressUtxos( + val result = requireChannel().createStub().getAddressUtxos( Service.GetAddressUtxosArg.newBuilder().setAddress(tAddress) .setStartHeight(startHeight.toLong()).build() ) @@ -131,8 +126,7 @@ class LightWalletGrpcService private constructor( ): List { if (blockHeightRange.isEmpty() || tAddress.isBlank()) return listOf() - channel.resetConnectBackoff() - val result = channel.createStub().getTaddressTxids( + val result = requireChannel().createStub().getTaddressTxids( Service.TransparentAddressBlockFilter.newBuilder().setAddress(tAddress) .setRange(blockHeightRange.toBlockRange()).build() ) @@ -153,6 +147,19 @@ class LightWalletGrpcService private constructor( ) } + // test code + var stateCount = 0 + var state: ConnectivityState? = null + private fun requireChannel(): ManagedChannel { + state = channel.getState(false).let { new -> + if (state == new) stateCount++ else stateCount = 0 + new + } + channel.resetConnectBackoff() + twig("getting channel isShutdown: ${channel.isShutdown} isTerminated: ${channel.isTerminated} getState: $state stateCount: $stateCount") + return channel + } + // // Utilities //