Tweak snode path error handling

Changes from f4281963882 (service repo)
This commit is contained in:
Anton Chekulaev 2020-12-17 16:56:19 +11:00
parent 37fc542136
commit 9002606917
2 changed files with 13 additions and 8 deletions

View File

@ -10,6 +10,7 @@ import org.session.libsignal.service.loki.api.utilities.HTTP
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
import org.session.libsignal.service.loki.utilities.getRandomElement import org.session.libsignal.service.loki.utilities.getRandomElement
import org.session.libsignal.service.loki.utilities.prettifiedDescription import org.session.libsignal.service.loki.utilities.prettifiedDescription
import org.session.libsignal.service.loki.utilities.retryIfNeeded
import java.security.SecureRandom import java.security.SecureRandom
import java.util.* import java.util.*
@ -27,11 +28,12 @@ class SwarmAPI private constructor(private val database: LokiAPIDatabaseProtocol
private val minimumSnodePoolCount = 64 private val minimumSnodePoolCount = 64
private val minimumSwarmSnodeCount = 2 private val minimumSwarmSnodeCount = 2
private val targetSwarmSnodeCount = 2 private val targetSwarmSnodeCount = 2
private val maxRetryCount = 6
/** /**
* A snode is kicked out of a swarm and/or the snode pool if it fails this many times. * A snode is kicked out of a swarm and/or the snode pool if it fails this many times.
*/ */
internal val snodeFailureThreshold = 4 internal val snodeFailureThreshold = 2
// endregion // endregion
// region Initialization // region Initialization
@ -115,7 +117,10 @@ class SwarmAPI private constructor(private val database: LokiAPIDatabaseProtocol
} else { } else {
val parameters = mapOf( "pubKey" to publicKey ) val parameters = mapOf( "pubKey" to publicKey )
return getRandomSnode().bind { return getRandomSnode().bind {
SnodeAPI.shared.invoke(Snode.Method.GetSwarm, it, publicKey, parameters) retryIfNeeded(maxRetryCount) {
SnodeAPI.shared.invoke(Snode.Method.GetSwarm, it, publicKey, parameters)
}
}.map(SnodeAPI.sharedContext) { }.map(SnodeAPI.sharedContext) {
parseSnodes(it).toSet() parseSnodes(it).toSet()
}.success { }.success {

View File

@ -44,11 +44,11 @@ public object OnionRequestAPI {
/** /**
* The number of times a path can fail before it's replaced. * The number of times a path can fail before it's replaced.
*/ */
private val pathFailureThreshold = 2 private val pathFailureThreshold = 1
/** /**
* The number of times a snode can fail before it's replaced. * The number of times a snode can fail before it's replaced.
*/ */
private val snodeFailureThreshold = 2 private val snodeFailureThreshold = 1
/** /**
* The number of paths to maintain. * The number of paths to maintain.
*/ */
@ -293,10 +293,10 @@ public object OnionRequestAPI {
*/ */
private fun sendOnionRequest(destination: Destination, payload: Map<*, *>, isJSONRequired: Boolean = true): Promise<Map<*, *>, Exception> { private fun sendOnionRequest(destination: Destination, payload: Map<*, *>, isJSONRequired: Boolean = true): Promise<Map<*, *>, Exception> {
val deferred = deferred<Map<*, *>, Exception>() val deferred = deferred<Map<*, *>, Exception>()
lateinit var guardSnode: Snode var guardSnode: Snode? = null
buildOnionForDestination(payload, destination).success { result -> buildOnionForDestination(payload, destination).success { result ->
guardSnode = result.guardSnode guardSnode = result.guardSnode
val url = "${guardSnode.address}:${guardSnode.port}/onion_req/v2" val url = "${guardSnode!!.address}:${guardSnode!!.port}/onion_req/v2"
val finalEncryptionResult = result.finalEncryptionResult val finalEncryptionResult = result.finalEncryptionResult
val onion = finalEncryptionResult.ciphertext val onion = finalEncryptionResult.ciphertext
if (destination is Destination.Server && onion.count().toDouble() > 0.75 * FileServerAPI.maxFileSize.toDouble()) { if (destination is Destination.Server && onion.count().toDouble() > 0.75 * FileServerAPI.maxFileSize.toDouble()) {
@ -365,14 +365,14 @@ public object OnionRequestAPI {
} }
val promise = deferred.promise val promise = deferred.promise
promise.fail { exception -> promise.fail { exception ->
val path = paths.firstOrNull { it.contains(guardSnode) } val path = if (guardSnode != null) paths.firstOrNull { it.contains(guardSnode!!) } else null
if (exception is HTTP.HTTPRequestFailedException) { if (exception is HTTP.HTTPRequestFailedException) {
fun handleUnspecificError() { fun handleUnspecificError() {
if (path == null) { return } if (path == null) { return }
var pathFailureCount = OnionRequestAPI.pathFailureCount[path] ?: 0 var pathFailureCount = OnionRequestAPI.pathFailureCount[path] ?: 0
pathFailureCount += 1 pathFailureCount += 1
if (pathFailureCount >= pathFailureThreshold) { if (pathFailureCount >= pathFailureThreshold) {
dropGuardSnode(guardSnode) dropGuardSnode(guardSnode!!)
path.forEach { snode -> path.forEach { snode ->
@Suppress("ThrowableNotThrown") @Suppress("ThrowableNotThrown")
SnodeAPI.shared.handleSnodeError(exception.statusCode, exception.json, snode, null) // Intentionally don't throw SnodeAPI.shared.handleSnodeError(exception.statusCode, exception.json, snode, null) // Intentionally don't throw