From 5ba3b5d13f50af48dd8d12e6dcd2e3150cd1c558 Mon Sep 17 00:00:00 2001 From: Dmitry Bushev Date: Thu, 11 Feb 2021 15:44:50 +0300 Subject: [PATCH] Abandon Terminating Language Server (#1463) Wait for the LS shutdown, spawn the new one, and only then reply to the client. --- .../LanguageServerController.scala | 17 +++++++++-------- .../languageserver/LanguageServerRegistry.scala | 8 ++++++++ .../DefaultDistributionConfiguration.scala | 9 +++++++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/languageserver/LanguageServerController.scala b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/languageserver/LanguageServerController.scala index d004f41c2156..3a12ab860f62 100644 --- a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/languageserver/LanguageServerController.scala +++ b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/languageserver/LanguageServerController.scala @@ -221,6 +221,7 @@ class LanguageServerController( case ServerDied => log.error(s"Language server died [$connectionInfo]") context.stop(self) + } private def removeClient( @@ -278,8 +279,9 @@ class LanguageServerController( maybeRequester.foreach(_ ! ServerShutdownTimedOut) stop() - case StartServer(_, _, _, _) => - sender() ! PreviousInstanceNotShutDown + case m: StartServer => + // This instance has not yet been shut down. Retry + context.parent.forward(Retry(m)) } private def waitingForChildren(): Receive = { case Terminated(_) => @@ -349,18 +351,17 @@ object LanguageServerController { case object ShutDownServer - /** Signals boot timeout. - */ + /** Signals boot timeout. */ case object BootTimeout - /** Boot command. - */ + /** Boot command. */ case object Boot - /** Signals shutdown timeout. - */ + /** Signals shutdown timeout. */ case object ShutdownTimeout case object ServerDied + case class Retry(message: Any) + } diff --git a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/languageserver/LanguageServerRegistry.scala b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/languageserver/LanguageServerRegistry.scala index a5215ef0b165..d6a42ad8e865 100644 --- a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/languageserver/LanguageServerRegistry.scala +++ b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/languageserver/LanguageServerRegistry.scala @@ -9,6 +9,7 @@ import org.enso.projectmanager.boot.configuration.{ SupervisionConfig, TimeoutConfig } +import org.enso.projectmanager.infrastructure.languageserver.LanguageServerController.Retry import org.enso.projectmanager.infrastructure.languageserver.LanguageServerProtocol.{ CheckIfServerIsRunning, KillThemAll, @@ -23,6 +24,8 @@ import org.enso.projectmanager.service.LoggingServiceDescriptor import org.enso.projectmanager.util.UnhandledLogging import org.enso.projectmanager.versionmanagement.DistributionConfiguration +import scala.concurrent.duration._ + /** An actor that routes request regarding lang. server lifecycle to the * right controller that manages the server. * It creates a controller actor, if a server doesn't exist. @@ -112,6 +115,11 @@ class LanguageServerRegistry( case CheckIfServerIsRunning(projectId) => sender() ! serverControllers.contains(projectId) + case Retry(message) => + context.system.scheduler.scheduleOnce(200.millis, self, message)( + context.dispatcher, + context.sender() + ) } } diff --git a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/versionmanagement/DefaultDistributionConfiguration.scala b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/versionmanagement/DefaultDistributionConfiguration.scala index 0a3083144df9..22dad296113c 100644 --- a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/versionmanagement/DefaultDistributionConfiguration.scala +++ b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/versionmanagement/DefaultDistributionConfiguration.scala @@ -11,7 +11,10 @@ import org.enso.runtimeversionmanager.distribution.{ DistributionManager, TemporaryDirectoryManager } -import org.enso.runtimeversionmanager.locking.{FileLockManager, ResourceManager} +import org.enso.runtimeversionmanager.locking.{ + ResourceManager, + ThreadSafeFileLockManager +} import org.enso.runtimeversionmanager.releases.ReleaseProvider import org.enso.runtimeversionmanager.releases.engine.{ EngineRelease, @@ -38,7 +41,9 @@ object DefaultDistributionConfiguration lazy val distributionManager = new DistributionManager(environment) /** @inheritdoc */ - lazy val lockManager = new FileLockManager(distributionManager.paths.locks) + lazy val lockManager = new ThreadSafeFileLockManager( + distributionManager.paths.locks + ) /** @inheritdoc */ lazy val resourceManager = new ResourceManager(lockManager)