diff --git a/metals/src/main/scala/scala/meta/internal/metals/ServerLivenessMonitor.scala b/metals/src/main/scala/scala/meta/internal/metals/ServerLivenessMonitor.scala index 7d96008371c..a5ae48829fd 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/ServerLivenessMonitor.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/ServerLivenessMonitor.scala @@ -5,7 +5,6 @@ import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledFuture import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean -import java.util.concurrent.atomic.AtomicReference import scala.concurrent.duration.Duration @@ -62,52 +61,38 @@ class ServerLivenessMonitor( pingInterval: Duration, bspStatus: BspStatus, ) { - private val state: AtomicReference[ServerLivenessMonitor.State] = - new AtomicReference(ServerLivenessMonitor.Idle) + @volatile private var lastPing: Long = 0 val scheduler: ScheduledExecutorService = Executors.newScheduledThreadPool(1) scribe.debug("starting server liveness monitor") def runnable(): Runnable = new Runnable { def run(): Unit = { - def now = System.currentTimeMillis() def lastIncoming = requestMonitor.lastIncoming .map(now - _) .getOrElse(pingInterval.toMillis) def notResponding = lastIncoming > (pingInterval.toMillis * 2) - def metalsIsIdle = - requestMonitor.lastOutgoing - .map(lastOutgoing => - (now - lastOutgoing) > metalsIdleInterval.toMillis - ) - .getOrElse(true) if (!metalsIsIdle) { - val currState = state.getAndUpdate { - case ServerLivenessMonitor.Idle => ServerLivenessMonitor.FirstPing - case _ => ServerLivenessMonitor.Running - } - currState match { - case ServerLivenessMonitor.Idle => - scribe.debug("setting server liveness monitor state to FirstPing") - case ServerLivenessMonitor.FirstPing => - scribe.debug("setting server liveness monitor state to Running") - case _ => - } - if (currState == ServerLivenessMonitor.Running) { - if (notResponding) { - bspStatus.noResponse() - } + if (lastPingOk && notResponding) { + bspStatus.noResponse() } scribe.debug("server liveness monitor: pinging build server...") + lastPing = now ping() - } else { - if (state.get() != ServerLivenessMonitor.Idle) - scribe.debug("setting server liveness monitor state to Idle") - state.set(ServerLivenessMonitor.Idle) } } } + + private def now = System.currentTimeMillis() + + def metalsIsIdle: Boolean = + requestMonitor.lastOutgoing + .map(lastOutgoing => (now - lastOutgoing) > metalsIdleInterval.toMillis) + .getOrElse(true) + + def lastPingOk: Boolean = now - lastPing < (pingInterval.toMillis * 2) + val scheduled: ScheduledFuture[_ <: Object] = scheduler.scheduleAtFixedRate( runnable(), pingInterval.toMillis, @@ -124,7 +109,6 @@ class ServerLivenessMonitor( bspStatus.disconnected() } - def getState: ServerLivenessMonitor.State = state.get() } object ServerLivenessMonitor { diff --git a/tests/unit/src/test/scala/tests/ServerLivenessMonitorSuite.scala b/tests/unit/src/test/scala/tests/ServerLivenessMonitorSuite.scala index cb9ea60af14..7b60b765f4b 100644 --- a/tests/unit/src/test/scala/tests/ServerLivenessMonitorSuite.scala +++ b/tests/unit/src/test/scala/tests/ServerLivenessMonitorSuite.scala @@ -33,19 +33,20 @@ class ServerLivenessMonitorSuite extends BaseSuite { ) bspStatus.connected() Thread.sleep(pingInterval.toMillis * 3 / 2) - assertEquals(livenessMonitor.getState, ServerLivenessMonitor.Idle) + assert(livenessMonitor.metalsIsIdle) server.sendRequest(false) Thread.sleep(pingInterval.toMillis * 2) - assertNotEquals(livenessMonitor.getState, ServerLivenessMonitor.Idle) + assert(!livenessMonitor.metalsIsIdle) Thread.sleep(pingInterval.toMillis * 5) - assertEquals(livenessMonitor.getState, ServerLivenessMonitor.Idle) + assert(livenessMonitor.metalsIsIdle) server.sendRequest(false) Thread.sleep(pingInterval.toMillis) server.sendRequest(false) server.sendRequest(false) Thread.sleep(pingInterval.toMillis * 2) server.sendRequest(false) - assertEquals(livenessMonitor.getState, ServerLivenessMonitor.Running) + assert(!livenessMonitor.metalsIsIdle) + assert(livenessMonitor.lastPingOk) assert(client.showMessageRequests == 0) livenessMonitor.shutdown() }