Refactor FailureCounter
This commit is contained in:
parent
08cd3d2f88
commit
fa2d699b1e
|
@ -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<String, Any>? = 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<String, Any>? = nu
|
|||
private fun logout(context: Context) {
|
||||
deleteDevice(context) {
|
||||
StartService.stopService()
|
||||
FailureHandler.clearFails()
|
||||
FailureCounter.clearFails()
|
||||
}
|
||||
AccountFactory.logout(context)
|
||||
AppStore(context).wipe()
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<EventSource?> = AtomicReference(null)
|
||||
// This is the last eventSource opened
|
||||
val eventSource: AtomicReference<EventSource?> = 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}"
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue