From 1ab93adc22b69db3c181ebe886fe7c0cf15fd205 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Fri, 20 Oct 2023 12:37:05 -0400 Subject: [PATCH] Reduces the amount of competing threads to restart connections with relays. --- .../vitorpamplona/amethyst/ServiceManager.kt | 10 +++- .../amethyst/service/NostrDataSource.kt | 4 +- .../amethyst/service/relays/Client.kt | 4 +- .../amethyst/service/relays/Relay.kt | 17 +++--- .../amethyst/service/relays/RelayPool.kt | 6 +-- .../vitorpamplona/amethyst/ui/MainActivity.kt | 52 +++++-------------- 6 files changed, 39 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt index 02050f908..8a568faaf 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt @@ -43,7 +43,7 @@ object ServiceManager { private var isStarted: Boolean = false // to not open amber in a loop trying to use auth relays and registering for notifications private var account: Account? = null - fun start(account: Account) { + private fun start(account: Account) { this.account = account ExternalSignerUtils.account = account start() @@ -51,6 +51,7 @@ object ServiceManager { @Synchronized fun start() { + Log.d("ServiceManager", "Pre Starting Relay Services $isStarted $account") if (isStarted && account != null) { return } @@ -158,6 +159,13 @@ object ServiceManager { start(account) } } + + fun forceRestartIfItShould() { + if (shouldPauseService) { + pause() + start() + } + } } object SingletonDiskCache { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt index ed8ee3a46..c853ba6be 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt @@ -50,7 +50,7 @@ abstract class NostrDataSource(val debugName: String) { // Log.e("ERROR", "Relay ${relay.url}: ${error.message}") } - override fun onRelayStateChange(type: Relay.Type, relay: Relay, subscriptionId: String?) { + override fun onRelayStateChange(type: Relay.StateType, relay: Relay, subscriptionId: String?) { // Log.d("RELAY", "Relay ${relay.url} ${when (type) { // Relay.Type.CONNECT -> "connected." // Relay.Type.DISCONNECT -> "disconnected." @@ -58,7 +58,7 @@ abstract class NostrDataSource(val debugName: String) { // Relay.Type.EOSE -> "sent all events it had stored." // }}") - if (type == Relay.Type.EOSE && subscriptionId != null && subscriptionId in subscriptions.keys) { + if (type == Relay.StateType.EOSE && subscriptionId != null && subscriptionId in subscriptions.keys) { // updates a per subscripton since date subscriptions[subscriptionId]?.updateEOSE( TimeUtils.fiveMinutesAgo(), // in case people's clock is slighly off. diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt index f012b0f21..9fa1804d6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt @@ -151,7 +151,7 @@ object Client : RelayPool.Listener { } @OptIn(DelicateCoroutinesApi::class) - override fun onRelayStateChange(type: Relay.Type, relay: Relay, channel: String?) { + override fun onRelayStateChange(type: Relay.StateType, relay: Relay, channel: String?) { // Releases the Web thread for the new payload. // May need to add a processing queue if processing new events become too costly. GlobalScope.launch(Dispatchers.Default) { @@ -207,7 +207,7 @@ object Client : RelayPool.Listener { /** * Connected to or disconnected from a relay */ - open fun onRelayStateChange(type: Relay.Type, relay: Relay, channel: String?) = Unit + open fun onRelayStateChange(type: Relay.StateType, relay: Relay, channel: String?) = Unit /** * When an relay saves or rejects a new event. diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt index dc10ec5a4..d45b97c7a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt @@ -128,7 +128,7 @@ class Relay( // Log.w("Relay", "Relay OnOpen, Loading All subscriptions $url") onConnected(this@Relay) - listeners.forEach { it.onRelayStateChange(this@Relay, Type.CONNECT, null) } + listeners.forEach { it.onRelayStateChange(this@Relay, StateType.CONNECT, null) } } override fun onMessage(webSocket: WebSocket, text: String) { @@ -152,7 +152,7 @@ class Relay( listeners.forEach { it.onRelayStateChange( this@Relay, - Type.DISCONNECTING, + StateType.DISCONNECTING, null ) } @@ -163,7 +163,7 @@ class Relay( markConnectionAsClosed() - listeners.forEach { it.onRelayStateChange(this@Relay, Type.DISCONNECT, null) } + listeners.forEach { it.onRelayStateChange(this@Relay, StateType.DISCONNECT, null) } } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { @@ -211,14 +211,14 @@ class Relay( listeners.forEach { it.onEvent(this@Relay, channel, event) if (afterEOSE) { - it.onRelayStateChange(this@Relay, Type.EOSE, channel) + it.onRelayStateChange(this@Relay, StateType.EOSE, channel) } } } "EOSE" -> listeners.forEach { afterEOSE = true // Log.w("Relay", "Relay onEOSE $url, $channel") - it.onRelayStateChange(this@Relay, Type.EOSE, channel) + it.onRelayStateChange(this@Relay, StateType.EOSE, channel) } "NOTICE" -> listeners.forEach { Log.w("Relay", "Relay onNotice $url, $channel") @@ -256,7 +256,8 @@ class Relay( } fun disconnect() { - // httpClient.dispatcher.executorService.shutdown() + checkNotInMainThread() + closingTimeInSeconds = TimeUtils.now() socket?.close(1000, "Normal close") socket = null @@ -360,7 +361,7 @@ class Relay( activeTypes == other.activeTypes } - enum class Type { + enum class StateType { // Websocket connected CONNECT, @@ -391,6 +392,6 @@ class Relay( * * @param type is 0 for disconnect and 1 for connect */ - fun onRelayStateChange(relay: Relay, type: Type, channel: String?) + fun onRelayStateChange(relay: Relay, type: StateType, channel: String?) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayPool.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayPool.kt index 7638d7b45..4c0d8e039 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayPool.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayPool.kt @@ -107,7 +107,7 @@ object RelayPool : Relay.Listener { fun onError(error: Error, subscriptionId: String, relay: Relay) - fun onRelayStateChange(type: Relay.Type, relay: Relay, channel: String?) + fun onRelayStateChange(type: Relay.StateType, relay: Relay, channel: String?) fun onSendResponse(eventId: String, success: Boolean, message: String, relay: Relay) @@ -123,9 +123,9 @@ object RelayPool : Relay.Listener { updateStatus() } - override fun onRelayStateChange(relay: Relay, type: Relay.Type, channel: String?) { + override fun onRelayStateChange(relay: Relay, type: Relay.StateType, channel: String?) { listeners.forEach { it.onRelayStateChange(type, relay, channel) } - if (type != Relay.Type.EOSE) { + if (type != Relay.StateType.EOSE) { updateStatus() } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index 51c3421ba..5320fdb33 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -6,7 +6,6 @@ import android.content.Intent import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities -import android.net.NetworkRequest import android.os.Build import android.os.Bundle import android.util.Log @@ -91,8 +90,8 @@ class MainActivity : AppCompatActivity() { DefaultMutedSetting.value = true // Only starts after login - GlobalScope.launch(Dispatchers.IO) { - if (ServiceManager.shouldPauseService) { + if (ServiceManager.shouldPauseService) { + GlobalScope.launch(Dispatchers.IO) { ServiceManager.start() } } @@ -101,24 +100,21 @@ class MainActivity : AppCompatActivity() { PushNotificationUtils.init(LocalPreferences.allSavedAccounts()) } - val networkRequest = NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .build() - - (getSystemService(ConnectivityManager::class.java) as ConnectivityManager) - .registerNetworkCallback(networkRequest, networkCallback) + (getSystemService(ConnectivityManager::class.java) as ConnectivityManager).registerDefaultNetworkCallback(networkCallback) } override fun onPause() { ServiceManager.cleanObservers() // if (BuildConfig.DEBUG) { - debugState(this) + GlobalScope.launch(Dispatchers.IO) { + debugState(this@MainActivity) + } // } if (ServiceManager.shouldPauseService) { - ServiceManager.pause() + GlobalScope.launch(Dispatchers.IO) { + ServiceManager.pause() + } } (getSystemService(ConnectivityManager::class.java) as ConnectivityManager) @@ -149,19 +145,6 @@ class MainActivity : AppCompatActivity() { @OptIn(DelicateCoroutinesApi::class) private val networkCallback = object : ConnectivityManager.NetworkCallback() { - // network is available for use - override fun onAvailable(network: Network) { - super.onAvailable(network) - Log.d("NETWORKCALLBACK", "onAvailable: Disconnecting and connecting again") - // Only starts after login - GlobalScope.launch(Dispatchers.IO) { - if (ServiceManager.shouldPauseService) { - ServiceManager.pause() - ServiceManager.start() - } - } - } - // Network capabilities have changed for the network override fun onCapabilitiesChanged( network: Network, @@ -171,20 +154,13 @@ class MainActivity : AppCompatActivity() { GlobalScope.launch(Dispatchers.IO) { val isOnMobileData = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) - Log.d("NETWORKCALLBACK", "onCapabilitiesChanged: hasMobileData $isOnMobileData") + val isOnWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + Log.d("ServiceManager NetworkCallback", "onCapabilitiesChanged: ${network.networkHandle} hasMobileData $isOnMobileData hasWifi $isOnWifi") - isOnMobileDataState.value = isOnMobileData - } - } + if (isOnMobileDataState.value != isOnMobileData) { + isOnMobileDataState.value = isOnMobileData - // lost network connection - override fun onLost(network: Network) { - super.onLost(network) - Log.d("NETWORKCALLBACK", "onLost: Disconnecting and pausing relay's connection") - // Only starts after login - GlobalScope.launch(Dispatchers.IO) { - if (ServiceManager.shouldPauseService) { - ServiceManager.pause() + ServiceManager.forceRestartIfItShould() } } }