From fa2d699b1e9a1b327c49a5456ed20c17a6378f92 Mon Sep 17 00:00:00 2001 From: sim Date: Fri, 29 Nov 2024 12:34:30 +0000 Subject: [PATCH] Refactor FailureCounter --- .../nextpush/activities/AppAction.kt | 6 +- .../distributor/nextpush/api/SSEListener.kt | 14 +-- .../nextpush/callback/BatteryCallback.kt | 4 +- .../nextpush/callback/NetworkCallback.kt | 6 +- .../{FailureHandler.kt => FailureCounter.kt} | 87 ++++++++++--------- .../nextpush/services/RestartWorker.kt | 6 +- .../nextpush/services/StartService.kt | 6 +- .../nextpush/utils/DebugInformation.kt | 4 +- 8 files changed, 70 insertions(+), 63 deletions(-) rename app/src/main/java/org/unifiedpush/distributor/nextpush/services/{FailureHandler.kt => FailureCounter.kt} (57%) diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/activities/AppAction.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/activities/AppAction.kt index e52797a..bee4c95 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/activities/AppAction.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/activities/AppAction.kt @@ -19,7 +19,7 @@ import org.unifiedpush.distributor.nextpush.account.AccountFactory import org.unifiedpush.distributor.nextpush.distributor.Distributor import org.unifiedpush.distributor.nextpush.distributor.Distributor.deleteApp import org.unifiedpush.distributor.nextpush.distributor.Distributor.deleteDevice -import org.unifiedpush.distributor.nextpush.services.FailureHandler +import org.unifiedpush.distributor.nextpush.services.FailureCounter import org.unifiedpush.distributor.nextpush.services.RestartWorker import org.unifiedpush.distributor.nextpush.services.StartService import org.unifiedpush.distributor.nextpush.utils.TAG @@ -64,7 +64,7 @@ class AppAction(private val type: Type, private val argv: Map? = nu private fun restartService(context: Context) { Log.d(TAG, "Restarting the Listener") - FailureHandler.clearFails() + FailureCounter.clearFails() StartService.stopService { RestartWorker.run(context, delay = 0) } @@ -73,7 +73,7 @@ class AppAction(private val type: Type, private val argv: Map? = nu private fun logout(context: Context) { deleteDevice(context) { StartService.stopService() - FailureHandler.clearFails() + FailureCounter.clearFails() } AccountFactory.logout(context) AppStore(context).wipe() diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/api/SSEListener.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/api/SSEListener.kt index 24638ec..f710ddb 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/api/SSEListener.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/api/SSEListener.kt @@ -21,7 +21,7 @@ import org.unifiedpush.distributor.nextpush.WakeLock import org.unifiedpush.distributor.nextpush.api.response.SSEResponse import org.unifiedpush.distributor.nextpush.distributor.Distributor.deleteAppFromSSE import org.unifiedpush.distributor.nextpush.distributor.Distributor.sendMessage -import org.unifiedpush.distributor.nextpush.services.FailureHandler +import org.unifiedpush.distributor.nextpush.services.FailureCounter import org.unifiedpush.distributor.nextpush.services.RestartWorker import org.unifiedpush.distributor.nextpush.services.StartService import org.unifiedpush.distributor.nextpush.utils.LowKeepAliveNotification @@ -37,7 +37,7 @@ class SSEListener(val context: Context) : EventSourceListener() { override var timeout: Long? = AppCompanion.keepalive.get().toLong() + TIMEOUT_TOLERANCE override fun onOpen(eventSource: EventSource, response: Response) { - FailureHandler.newEventSource(context, eventSource) + FailureCounter.newEventSource(context, eventSource) StartingTimer.scheduleNewTimer(context, eventSource) WakeLock.instance?.release() try { @@ -62,7 +62,7 @@ class SSEListener(val context: Context) : EventSourceListener() { "ping" -> { AppCompanion.pinged.set(true) - FailureHandler.newPing(context) + FailureCounter.newPing(context) } "keepalive" -> { @@ -107,7 +107,7 @@ class SSEListener(val context: Context) : EventSourceListener() { eventSource.cancel() WakeLock.instance?.release() if (!shouldRestart()) return - if (FailureHandler.newFail(context, eventSource)) { + if (FailureCounter.addFail(context, eventSource)) { clearDebugVars() RestartWorker.run(context, delay = 0) } @@ -131,9 +131,9 @@ class SSEListener(val context: Context) : EventSourceListener() { clearDebugVars() return } - if (FailureHandler.newFail(context, eventSource)) { + if (FailureCounter.addFail(context, eventSource)) { clearDebugVars() - val delay = when (FailureHandler.nFails()) { + val delay = when (FailureCounter.nFails) { 1 -> 2 // 2sec 2 -> 5 // 5sec 3 -> 20 // 20sec @@ -186,7 +186,7 @@ class SSEListener(val context: Context) : EventSourceListener() { !AppCompanion.booting.getAndSet(false) ) { Timer().schedule(45_000L) { // 45 secs - if (FailureHandler.newFail(context, eventSource)) { + if (FailureCounter.addFail(context, eventSource)) { StartService.stopService() NoStartNotification(context).showSingle() } diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/callback/BatteryCallback.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/callback/BatteryCallback.kt index 7871f0b..a061ee3 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/callback/BatteryCallback.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/callback/BatteryCallback.kt @@ -7,7 +7,7 @@ import android.content.IntentFilter import android.os.BatteryManager import android.util.Log import org.unifiedpush.distributor.nextpush.AppCompanion -import org.unifiedpush.distributor.nextpush.services.FailureHandler +import org.unifiedpush.distributor.nextpush.services.FailureCounter import org.unifiedpush.distributor.nextpush.services.RestartWorker import org.unifiedpush.distributor.nextpush.services.StartService import org.unifiedpush.distributor.nextpush.utils.TAG @@ -37,7 +37,7 @@ class BatteryCallback : BroadcastReceiver() { } private fun restartServer(context: Context) { - if (!FailureHandler.hasFailed()) { + if (FailureCounter.isRunningWithoutFailure) { StartService.stopService { RestartWorker.run(context, delay = 0) } diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/callback/NetworkCallback.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/callback/NetworkCallback.kt index 381d281..e629154 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/callback/NetworkCallback.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/callback/NetworkCallback.kt @@ -10,7 +10,7 @@ import java.lang.Exception import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicReference import org.unifiedpush.distributor.nextpush.AppCompanion -import org.unifiedpush.distributor.nextpush.services.FailureHandler +import org.unifiedpush.distributor.nextpush.services.FailureCounter import org.unifiedpush.distributor.nextpush.services.RegistrationCountCache import org.unifiedpush.distributor.nextpush.services.RestartWorker import org.unifiedpush.distributor.nextpush.utils.TAG @@ -49,7 +49,7 @@ class NetworkCallback(val context: Context) : ConnectivityManager.NetworkCallbac */ private fun noInternet() { AppCompanion.hasInternet.set(false) - FailureHandler.once() + FailureCounter.setFailOnce() } /** @@ -58,7 +58,7 @@ class NetworkCallback(val context: Context) : ConnectivityManager.NetworkCallbac */ private fun backOnline() { // We first check if there is a fail registered, else a worker will run in 2 seconds - if (FailureHandler.hasFailed(orNeverStart = false) && RegistrationCountCache.oneOrMore(context)) { + if (FailureCounter.hasFailed && RegistrationCountCache.oneOrMore(context)) { Log.d(TAG, "Restarting worker") RestartWorker.run(context, delay = 0) } // else, it retries in max 2sec diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/services/FailureHandler.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/services/FailureCounter.kt similarity index 57% rename from app/src/main/java/org/unifiedpush/distributor/nextpush/services/FailureHandler.kt rename to app/src/main/java/org/unifiedpush/distributor/nextpush/services/FailureCounter.kt index a0e447e..e3c4332 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/services/FailureHandler.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/services/FailureCounter.kt @@ -10,40 +10,49 @@ import org.unifiedpush.distributor.nextpush.utils.DisconnectedNotification import org.unifiedpush.distributor.nextpush.utils.NoPingNotification import org.unifiedpush.distributor.nextpush.utils.TAG -object FailureHandler { +object FailureCounter { - private val ttlFails = AtomicInteger(0) - private val nFails = AtomicInteger(0) - private val nFailsBeforePing = AtomicInteger(0) + private object Atomics { + val ttlFails = AtomicInteger(0) + val nFails = AtomicInteger(0) + val nFailsBeforePing = AtomicInteger(0) - // This is the last eventSource opened - private val eventSource: AtomicReference = AtomicReference(null) + // This is the last eventSource opened + val eventSource: AtomicReference = AtomicReference(null) + } /** * Is the [eventSource] the current one? * Any eventSource is considered as the current if none is saved. */ private fun isCurrentEventSource(eventSource: EventSource?): Boolean { - return this.eventSource.get()?.let { + return Atomics.eventSource.get()?.let { it == eventSource } ?: true } + /** + * When a new event source is set, we cancel the previous one + * and set [Atomics.nFails] to 0 and remove [DisconnectedNotification] + */ fun newEventSource(context: Context, eventSource: EventSource) { Log.d(TAG, "newEvent/Eventsource: $eventSource") - this.eventSource.getAndSet(eventSource)?.cancel() - nFails.set(0) + Atomics.eventSource.getAndSet(eventSource)?.cancel() + Atomics.nFails.set(0) DisconnectedNotification(context).delete() } + /** + * When a new ping is recorded, we set [Atomics.nFailsBeforePing] to 0 + * and remove [NoPingNotification] + */ fun newPing(context: Context) { - nFailsBeforePing.set(0) + Atomics.nFailsBeforePing.set(0) NoPingNotification(context).delete() } - fun nFails(): Int { - return nFails.get() - } + val nFails: Int + get() = Atomics.nFails.get() /** * Check the [eventSource] and increase the counter of failed events. @@ -58,23 +67,23 @@ object FailureHandler { * * @return `true` if the fail is from the current eventSource */ - fun newFail(context: Context, eventSource: EventSource): Boolean { + fun addFail(context: Context, eventSource: EventSource): Boolean { Log.d(TAG, "newFail/Eventsource: $eventSource") // ignore fails from a possible old eventSource // if we are already reconnected return if (isCurrentEventSource(eventSource)) { Log.d(TAG, "EventSource is known or null") - ttlFails.getAndIncrement() - if (nFails.incrementAndGet() == 2) { + Atomics.ttlFails.getAndIncrement() + if (Atomics.nFails.incrementAndGet() == 2) { DisconnectedNotification(context).showSingle() } if (AppCompanion.started.get() && !AppCompanion.pinged.get()) { Log.d(TAG, "The service has started and it has never received a ping.") - if (nFailsBeforePing.incrementAndGet() == 5) { + if (Atomics.nFailsBeforePing.incrementAndGet() == 5) { NoPingNotification(context).showSingle() } } - this.eventSource.getAndSet(null)?.cancel() + Atomics.eventSource.getAndSet(null)?.cancel() true } else { Log.d(TAG, "This is an old EventSource.") @@ -88,37 +97,35 @@ object FailureHandler { * * Used when there is no Internet access. */ - fun once() { - Log.d(TAG, "once/Eventsource: $eventSource") - nFails.set(1) - this.eventSource.getAndSet(null)?.cancel() + fun setFailOnce() { + Log.d(TAG, "setFailOnce") + Atomics.nFails.set(1) + Atomics.eventSource.getAndSet(null)?.cancel() } fun clearFails() { - ttlFails.set(0) - nFails.set(0) - nFailsBeforePing.set(0) - this.eventSource.getAndSet(null)?.cancel() + Atomics.ttlFails.set(0) + Atomics.nFails.set(0) + Atomics.nFailsBeforePing.set(0) + Atomics.eventSource.getAndSet(null)?.cancel() } /** - * Is the service started and and has already failed once ? - * - * If [orNeverStart] is true (default) we consider a non-started service as a failed service + * Is an eventSource recorded, and there isn't any failure ? */ - fun hasFailed(orNeverStart: Boolean = true): Boolean { - // nFails > 0 to be sure it is not actually restarting - return if (orNeverStart) { - eventSource.get() == null - } else { - false - } || nFails.get() > 0 - } + val isRunningWithoutFailure: Boolean + get() = Atomics.eventSource.get() != null && !hasFailed + + /** + * Has the service failed at least once ? + */ + val hasFailed: Boolean + get() = nFails > 0 fun getDebugInfo(): String { - return "ttlFails: ${ttlFails.get()}\n" + + return "ttlFails: ${Atomics.ttlFails.get()}\n" + "nFails: $nFails\n" + - "nFailsBeforePing: $nFailsBeforePing\n" + - "eventSource null: ${eventSource.get() == null}" + "nFailsBeforePing: ${Atomics.nFailsBeforePing.get()}\n" + + "eventSource null: ${Atomics.eventSource.get() == null}" } } diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/services/RestartWorker.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/services/RestartWorker.kt index 06fe094..65ca986 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/services/RestartWorker.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/services/RestartWorker.kt @@ -38,12 +38,12 @@ class RestartWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params if (currentDate.after(restartDate)) { Log.d(TAG, "We should have received an event before ${restartDate.time}. Restarting") /** - * If there is at least one failure, we do not update [FailureHandler]'s counter, + * If there is at least one failure, we do not update [FailureCounter]'s counter, * it will be done by the next requests. * Else we add one failure to be sure the service restarts. */ - if (!FailureHandler.hasFailed()) { - FailureHandler.once() + if (FailureCounter.isRunningWithoutFailure) { + FailureCounter.setFailOnce() } StartService.startListener(applicationContext) // We consider this run as the first event diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/services/StartService.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/services/StartService.kt index 340cfad..b516273 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/services/StartService.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/services/StartService.kt @@ -74,7 +74,7 @@ class StartService : Service() { private fun startService() { // If the service is running and we don't have any fail // In case somehow startService is called when everything is fine - if (isServiceStarted && !FailureHandler.hasFailed()) return + if (isServiceStarted && FailureCounter.isRunningWithoutFailure) return getAccount(this) ?: run { Log.d(TAG, "No account found") return @@ -103,7 +103,7 @@ class StartService : Service() { fun startListener(context: Context) { val hasRegistration = RegistrationCountCache.oneOrMore(context) if (isServiceStarted && - !FailureHandler.hasFailed() && + FailureCounter.isRunningWithoutFailure && // We return only if there is one or more registration // because if there is no registration, this is a request to stop the SSE hasRegistration @@ -117,7 +117,7 @@ class StartService : Service() { } Log.d(TAG, "Starting the Listener") Log.d(TAG, "Service is started: $isServiceStarted") - Log.d(TAG, "nFails: ${FailureHandler.nFails()}") + Log.d(TAG, "nFails: ${FailureCounter.nFails}") Log.d(TAG, "Has registration: $hasRegistration") val serviceIntent = Intent(context, StartService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/utils/DebugInformation.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/utils/DebugInformation.kt index 38e1410..aeeb815 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/utils/DebugInformation.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/utils/DebugInformation.kt @@ -2,7 +2,7 @@ package org.unifiedpush.distributor.nextpush.utils import java.text.SimpleDateFormat import org.unifiedpush.distributor.nextpush.AppCompanion -import org.unifiedpush.distributor.nextpush.services.FailureHandler +import org.unifiedpush.distributor.nextpush.services.FailureCounter import org.unifiedpush.distributor.nextpush.services.StartService fun getDebugInfo(): String { @@ -14,5 +14,5 @@ fun getDebugInfo(): String { "Keepalive: ${AppCompanion.keepalive.get()}\n" + "SSE started: ${AppCompanion.started}\n" + "SSE pinged: ${AppCompanion.pinged}\n" + - FailureHandler.getDebugInfo() + FailureCounter.getDebugInfo() }