Limit TaskProgress threads

I noticed some flickering in super shell progress lines and realized
that it was because there were multiple progress threads running
concurrently. This is problematic because each thread has a completely
different state so if each thread has an active task, the display will
flicker between the two tasks. I think this is caused primarily by
dynamic tasks. At least the example where I was seeing it was caused by
a dynamic task.
This commit is contained in:
Ethan Atkins 2019-09-24 10:30:25 -07:00
parent ccecf1e412
commit f0bec6d9e3
3 changed files with 39 additions and 25 deletions

View File

@ -224,29 +224,33 @@ object EvaluateTask {
structure: BuildStructure,
state: State
): ExecuteProgress[Task] = {
val maker: Seq[Keys.TaskProgress] = getSetting(
Keys.progressReports,
Seq(),
extracted,
structure
)
val progressReporter = extracted.get(progressState in ThisBuild).map { ps =>
ps.reset()
ConsoleAppender.setShowProgress(true)
val appender = MainAppender.defaultScreen(StandardMain.console)
appender match {
case c: ConsoleAppender => c.setProgressState(ps)
case _ =>
state.get(currentTaskProgress).map(_.progress).getOrElse {
val maker: Seq[Keys.TaskProgress] = getSetting(
Keys.progressReports,
Seq(),
extracted,
structure
)
val progressReporter = extracted.getOpt(progressState in ThisBuild).flatMap {
case Some(ps) =>
ps.reset()
ConsoleAppender.setShowProgress(true)
val appender = MainAppender.defaultScreen(StandardMain.console)
appender match {
case c: ConsoleAppender => c.setProgressState(ps)
case _ =>
}
val log = LogManager.progressLogger(appender)
Some(new TaskProgress(log))
case _ => None
}
val reporters = maker.map(_.progress) ++ progressReporter ++
(if (SysProp.taskTimings) new TaskTimings(reportOnShutdown = false) :: Nil else Nil)
reporters match {
case xs if xs.isEmpty => ExecuteProgress.empty[Task]
case xs if xs.size == 1 => xs.head
case xs => ExecuteProgress.aggregate[Task](xs)
}
val log = LogManager.progressLogger(appender)
new TaskProgress(log)
}
val reporters = maker.map(_.progress) ++ progressReporter ++
(if (SysProp.taskTimings) new TaskTimings(reportOnShutdown = false) :: Nil else Nil)
reporters match {
case xs if xs.isEmpty => ExecuteProgress.empty[Task]
case xs if xs.size == 1 => xs.head
case xs => ExecuteProgress.aggregate[Task](xs)
}
}
// TODO - Should this pull from Global or from the project itself?

View File

@ -482,6 +482,7 @@ object Keys {
object TaskProgress {
def apply(progress: ExecuteProgress[Task]): TaskProgress = new TaskProgress(progress)
}
private[sbt] val currentTaskProgress = AttributeKey[TaskProgress]("current-task-progress")
val useSuperShell = settingKey[Boolean]("Enables (true) or disables the super shell.")
val turbo = settingKey[Boolean]("Enables (true) or disables optional performance features.")
// This key can be used to add custom ExecuteProgress instances

View File

@ -179,10 +179,18 @@ object MainLoop {
val channelName = exec.source map (_.channelName)
StandardMain.exchange publishEventMessage
ExecStatusEvent("Processing", channelName, exec.execId, Vector())
try {
def process(): State = {
val newState = Command.process(exec.commandLine, state)
val progressState = state.get(sbt.Keys.currentTaskProgress) match {
case Some(_) => state
case _ =>
if (state.get(Keys.stateBuildStructure).isDefined) {
val extracted = Project.extract(state)
val progress = EvaluateTask.executeProgress(extracted, extracted.structure, state)
state.put(sbt.Keys.currentTaskProgress, new Keys.TaskProgress(progress))
} else state
}
val newState = Command.process(exec.commandLine, progressState)
if (exec.commandLine.contains("session"))
newState.get(hasCheckedMetaBuild).foreach(_.set(false))
val doneEvent = ExecStatusEvent(
@ -198,7 +206,8 @@ object MainLoop {
} else { // send back a notification
StandardMain.exchange publishEventMessage doneEvent
}
newState
newState.get(sbt.Keys.currentTaskProgress).foreach(_.progress.stop())
newState.remove(sbt.Keys.currentTaskProgress)
}
// The split on space is to handle 'reboot full' and 'reboot'.
state.currentCommand.flatMap(_.commandLine.trim.split(" ").headOption) match {