@@ -6,6 +6,7 @@ import kotlinx.coroutines.channels.consumeEach
66import kotlinx.coroutines.flow.MutableStateFlow
77import kotlinx.coroutines.flow.StateFlow
88import org.datepollsystems.waiterrobot.mediator.core.di.injectLoggerForClass
9+ import org.datepollsystems.waiterrobot.mediator.printer.service.PrinterService
910import org.datepollsystems.waiterrobot.mediator.utils.SuspendingExponentialBackoff
1011import org.datepollsystems.waiterrobot.mediator.ws.messages.AbstractWsMessage
1112import org.datepollsystems.waiterrobot.mediator.ws.messages.WsMessageBody
@@ -14,6 +15,8 @@ import java.time.Duration
1415import java.util.concurrent.atomic.AtomicBoolean
1516import kotlin.reflect.KClass
1617
18+ private const val MAX_CONSECUTIVE_FAILS = 10
19+
1720/* *
1821 * Handles a websocket session and auto recovers on an exception in the session.
1922 * For auto recover an exponential backoff is used.
@@ -32,6 +35,9 @@ class MediatorWebSocketManager : KoinComponent {
3235 private val registerLock = Object ()
3336 private val handlers: HandlerMap = mutableMapOf ()
3437
38+ private var websocketExceptionCount = 0 // Counter for consecutive exceptions
39+ private var hasPrintedWebsocketError = false
40+
3541 @Suppress(" MagicNumber" )
3642 private val suspendingBackoff = SuspendingExponentialBackoff (
3743 initialDelay = Duration .ofMillis(500 ),
@@ -73,15 +79,18 @@ class MediatorWebSocketManager : KoinComponent {
7379 // This should only be triggered on Errors as ktor already handles connection loss internally
7480 if (! closedIntentional.get()) {
7581 logger.w(e) { " WebSocket session completed" }
82+ handleConsecutiveWebsocketErrors(e)
7683 suspendingBackoff.backoff(e)
7784 startWatching()
7885 } else {
7986 logger.d(e) { " WebSocket session completed" }
8087 }
8188 }
8289 setIsConnected(true )
90+ handleConsecutiveWebsocketErrors()
8391 } catch (e: Exception ) {
8492 closeCurrentSession()
93+ handleConsecutiveWebsocketErrors(e)
8594 suspendingBackoff.backoff(e)
8695 return @launch startWatching()
8796 }
@@ -92,6 +101,22 @@ class MediatorWebSocketManager : KoinComponent {
92101 }
93102 }
94103
104+ private fun handleConsecutiveWebsocketErrors (e : Throwable ? = null) {
105+ if (e != null ) {
106+ if (! hasPrintedWebsocketError && websocketExceptionCount >= MAX_CONSECUTIVE_FAILS ) {
107+ PrinterService .printNetworkDisconnect()
108+ hasPrintedWebsocketError = true
109+
110+ return
111+ }
112+
113+ websocketExceptionCount++
114+ } else {
115+ websocketExceptionCount = 0
116+ hasPrintedWebsocketError = false
117+ }
118+ }
119+
95120 fun close () {
96121 if (closed.getAndSet(true )) return
97122 closedIntentional.set(true )
0 commit comments