ruach
ruach

Reputation: 1469

scala: How can I define an order of execution among multiple dependent tasks in SBT settings?

I couldn't understand how the sbt (excerpted from SBT reference manual) determines an order of execution among tasks.

This code explains how the SBT can determine the execution order among the multiple dependent tasks. As far as I know, SBT executes multiple tasks which are dependent on one task in parallel, so it couldn't explicitly specify the order of execution among the multiple dependent tasks, which are used with .value method.

val startServer = taskKey[Unit]("start server")
val stopServer = taskKey[Unit]("stop server")
val sampleIntTask = taskKey[Int]("A sample int task.")
val sampleStringTask = taskKey[String]("A sample string task.")

lazy val commonSettings = Seq(
  organization := "com.example",
  version := "0.1.0-SNAPSHOT"
)

lazy val library = (project in file("library"))
  .settings(
    commonSettings,
    startServer := {
      println("starting...")
      Thread.sleep(500)
    },
    stopServer := {
      println("stopping...")
      Thread.sleep(500)
    },
    sampleIntTask := {
      startServer.value
      val sum = 1 + 2
      println("sum: " + sum)
      stopServer.value // THIS WON'T WORK
      sum
    },
    sampleStringTask := {
      startServer.value
      val s = sampleIntTask.value.toString
      println("s: " + s)
      s
    }
  )

In the above code, sampleStringTask has a dependency on the startServer and stopServer tasks and the output messages can be different depending on which task is executed first.

Here is the modified version of the same code that always finishes with printing "stopping...."

lazy val library = (project in file("library"))
  .settings(
    commonSettings,
    startServer := {
      println("starting...")
      Thread.sleep(500)
    },
    sampleIntTask := {
      startServer.value
      val sum = 1 + 2
      println("sum: " + sum)
      sum
    },
    sampleStringTask := {
      startServer.value
      val s = sampleIntTask.value.toString
      println("s: " + s)
      s
    },
    sampleStringTask := {
      val old = sampleStringTask.value
      println("stopping...")
      Thread.sleep(500)
      old
    }
  )

In the modified code, it suggests a way to define a fixed order of execution among the multiple tasks by implementing the sampleStringTask twice. Here the second definition of the task embraces behaviors of the stopServer task described in the below code.

However, I couldn't understand how these two functions are used to specify the exact order of execution. It seems the second function overrides the task definition of the sampleStringTask. How does it affect the ordering? Are these two overridden tasks are executed in sequential?

Upvotes: 1

Views: 332

Answers (1)

KarateKid
KarateKid

Reputation: 3436

In the second example, when sampleStringTask is redefined it ensures that the first definition is executed before the redefined definition. It is important to understand that the redefined definition doesn't override the first definition, instead it uses or depends upon the first definition. And since the task dependencies are evaluated before evaluating the task (partial ordering), the ordering is maintained here.

Upvotes: 1

Related Questions