mirror of https://github.com/sbt/sbt.git
commit
45f5019ee0
|
|
@ -884,7 +884,11 @@ object BuiltinCommands {
|
|||
val exchange = StandardMain.exchange
|
||||
val s1 = exchange run s0
|
||||
exchange publishEventMessage ConsolePromptEvent(s0)
|
||||
val exec: Exec = exchange.blockUntilNextExec
|
||||
val minGCInterval = Project
|
||||
.extract(s1)
|
||||
.getOpt(Keys.minForcegcInterval)
|
||||
.getOrElse(GCUtil.defaultMinForcegcInterval)
|
||||
val exec: Exec = exchange.blockUntilNextExec(minGCInterval, s1.globalLogging.full)
|
||||
val newState = s1
|
||||
.copy(
|
||||
onFailure = Some(Exec(Shell, None)),
|
||||
|
|
|
|||
|
|
@ -11,32 +11,36 @@ package internal
|
|||
import java.io.IOException
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.atomic._
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.annotation.tailrec
|
||||
import BasicKeys.{
|
||||
autoStartServer,
|
||||
serverHost,
|
||||
serverPort,
|
||||
fullServerHandlers,
|
||||
logLevel,
|
||||
serverAuthentication,
|
||||
serverConnectionType,
|
||||
serverHost,
|
||||
serverLogLevel,
|
||||
fullServerHandlers,
|
||||
logLevel
|
||||
serverPort
|
||||
}
|
||||
import java.net.Socket
|
||||
|
||||
import sbt.Watched.NullLogger
|
||||
import sjsonnew.JsonFormat
|
||||
import sjsonnew.shaded.scalajson.ast.unsafe._
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.util.{ Success, Failure, Try }
|
||||
import scala.concurrent.duration._
|
||||
import scala.util.{ Failure, Success, Try }
|
||||
import sbt.io.syntax._
|
||||
import sbt.io.{ Hash, IO }
|
||||
import sbt.internal.server._
|
||||
import sbt.internal.langserver.{ LogMessageParams, MessageType }
|
||||
import sbt.internal.util.{ StringEvent, ObjectEvent, MainAppender }
|
||||
import sbt.internal.util.{ MainAppender, ObjectEvent, StringEvent }
|
||||
import sbt.internal.util.codec.JValueFormats
|
||||
import sbt.protocol.{ EventMessage, ExecStatusEvent }
|
||||
import sbt.util.{ Level, Logger, LogExchange }
|
||||
import sbt.util.{ Level, LogExchange, Logger }
|
||||
|
||||
/**
|
||||
* The command exchange merges multiple command channels (e.g. network and console),
|
||||
|
|
@ -59,22 +63,34 @@ private[sbt] final class CommandExchange {
|
|||
def channels: List[CommandChannel] = channelBuffer.toList
|
||||
def subscribe(c: CommandChannel): Unit = channelBufferLock.synchronized(channelBuffer.append(c))
|
||||
|
||||
def blockUntilNextExec: Exec = blockUntilNextExec(Duration.Inf, NullLogger)
|
||||
// periodically move all messages from all the channels
|
||||
@tailrec def blockUntilNextExec: Exec = {
|
||||
@tailrec def slurpMessages(): Unit =
|
||||
channels.foldLeft(Option.empty[Exec]) { _ orElse _.poll } match {
|
||||
case None => ()
|
||||
case Some(x) =>
|
||||
commandQueue.add(x)
|
||||
slurpMessages
|
||||
private[sbt] def blockUntilNextExec(interval: Duration, logger: Logger): Exec = {
|
||||
@tailrec def impl(deadline: Option[Deadline]): Exec = {
|
||||
@tailrec def slurpMessages(): Unit =
|
||||
channels.foldLeft(Option.empty[Exec]) { _ orElse _.poll } match {
|
||||
case None => ()
|
||||
case Some(x) =>
|
||||
commandQueue.add(x)
|
||||
slurpMessages()
|
||||
}
|
||||
slurpMessages()
|
||||
Option(commandQueue.poll) match {
|
||||
case Some(x) => x
|
||||
case None =>
|
||||
Thread.sleep(2)
|
||||
val newDeadline = if (deadline.fold(false)(_.isOverdue())) {
|
||||
GCUtil.forceGcWithInterval(interval, logger)
|
||||
None
|
||||
} else deadline
|
||||
impl(newDeadline)
|
||||
}
|
||||
slurpMessages()
|
||||
Option(commandQueue.poll) match {
|
||||
case Some(x) => x
|
||||
case None =>
|
||||
Thread.sleep(50)
|
||||
blockUntilNextExec
|
||||
}
|
||||
// Do not manually run GC until the user has been idling for at least the min gc interval.
|
||||
impl(interval match {
|
||||
case d: FiniteDuration => Some(d.fromNow)
|
||||
case _ => None
|
||||
})
|
||||
}
|
||||
|
||||
def run(s: State): State = {
|
||||
|
|
@ -83,7 +99,7 @@ private[sbt] final class CommandExchange {
|
|||
consoleChannel = Some(console0)
|
||||
subscribe(console0)
|
||||
}
|
||||
val autoStartServerAttr = (s get autoStartServer) match {
|
||||
val autoStartServerAttr = s get autoStartServer match {
|
||||
case Some(bool) => bool
|
||||
case None => true
|
||||
}
|
||||
|
|
@ -261,13 +277,13 @@ private[sbt] final class CommandExchange {
|
|||
val toDel: ListBuffer[CommandChannel] = ListBuffer.empty
|
||||
def json: JValue = JObject(
|
||||
JField("type", JString(event.contentType)),
|
||||
(Vector(JField("message", event.json), JField("level", JString(event.level.toString))) ++
|
||||
Vector(JField("message", event.json), JField("level", JString(event.level.toString))) ++
|
||||
(event.channelName.toVector map { channelName =>
|
||||
JField("channelName", JString(channelName))
|
||||
}) ++
|
||||
(event.execId.toVector map { execId =>
|
||||
JField("execId", JString(execId))
|
||||
})): _*
|
||||
}): _*
|
||||
)
|
||||
channels collect {
|
||||
case c: ConsoleChannel =>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ private[sbt] object GCUtil {
|
|||
// Returns the default force garbage collection flag,
|
||||
// as specified by system properties.
|
||||
val defaultForceGarbageCollection: Boolean = true
|
||||
val defaultMinForcegcInterval: Duration = 60.seconds
|
||||
val defaultMinForcegcInterval: Duration = 10.minutes
|
||||
val lastGcCheck: AtomicLong = new AtomicLong(0L)
|
||||
|
||||
def forceGcWithInterval(minForcegcInterval: Duration, log: Logger): Unit = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue