fix: don't reconnect when command was superseded

We only want to do the reconnect if the previous command was the
schedule reconnect, if the websocket connection got started another way
or was closed, we don't want to do the reconnect.
This commit is contained in:
Jannis Mattheis
2025-02-15 11:45:12 +01:00
parent a82d985027
commit 07b1da9de1
2 changed files with 24 additions and 10 deletions

View File

@@ -1,6 +1,7 @@
package com.github.gotify.service
import android.app.AlarmManager
import android.app.AlarmManager.OnAlarmListener
import android.os.Build
import android.os.Handler
import android.os.Looper
@@ -29,9 +30,10 @@ internal class WebSocketConnection(
private val ID = AtomicLong(0)
}
private var alarmManagerCallback: OnAlarmListener? = null
private var handlerCallback: Runnable? = null
private val client: OkHttpClient
private val reconnectHandler = Handler(Looper.getMainLooper())
private val reconnectCallback = Runnable { start() }
private var errorCount = 0
private var webSocket: WebSocket? = null
@@ -106,6 +108,13 @@ internal class WebSocketConnection(
@Synchronized
fun close() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
alarmManagerCallback?.run(alarmManager::cancel)
alarmManagerCallback = null
} else {
handlerCallback?.run(reconnectHandler::removeCallbacks)
handlerCallback = null
}
if (webSocket != null) {
webSocket?.close(1000, "")
closed()
@@ -119,8 +128,10 @@ internal class WebSocketConnection(
state = State.Disconnected
}
fun scheduleReconnectNow(seconds: Long) = scheduleReconnect(ID.get(), seconds)
@Synchronized
fun scheduleReconnect(seconds: Long) {
fun scheduleReconnect(id: Long, seconds: Long) {
if (state == State.Connecting || state == State.Connected) {
return
}
@@ -130,17 +141,23 @@ internal class WebSocketConnection(
Logger.info("WebSocket: scheduling a restart in $seconds second(s) (via alarm manager)")
val future = Calendar.getInstance()
future.add(Calendar.SECOND, seconds.toInt())
alarmManagerCallback?.run(alarmManager::cancel)
val cb = OnAlarmListener { syncExec(id) { start() } }
alarmManagerCallback = cb
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
future.timeInMillis,
"reconnect-tag",
{ start() },
cb,
null
)
} else {
Logger.info("WebSocket: scheduling a restart in $seconds second(s)")
reconnectHandler.removeCallbacks(reconnectCallback)
reconnectHandler.postDelayed(reconnectCallback, TimeUnit.SECONDS.toMillis(seconds))
handlerCallback?.run(reconnectHandler::removeCallbacks)
val cb = Runnable { syncExec(id) { start() } }
handlerCallback = cb
reconnectHandler.postDelayed(cb, TimeUnit.SECONDS.toMillis(seconds))
}
}
@@ -190,7 +207,7 @@ internal class WebSocketConnection(
val minutes = (errorCount * 2 - 1).coerceAtMost(20)
onFailure.execute(response?.message ?: "unreachable", minutes)
scheduleReconnect(TimeUnit.MINUTES.toSeconds(minutes.toLong()))
scheduleReconnect(id, TimeUnit.MINUTES.toSeconds(minutes.toLong()))
}
super.onFailure(webSocket, t, response)
}

View File

@@ -172,10 +172,7 @@ internal class WebSocketService : Service() {
}
private fun doReconnect() {
if (connection == null) {
return
}
connection!!.scheduleReconnect(15)
connection?.scheduleReconnectNow(15)
}
private fun onFailure(status: String, minutes: Int) {