Track a small async-style workflow through stages.

pipeline-state A larger async workflow is often a series of state changes: queued, started, retried, and complete or delayed. Local variables make those stages replayable.

Pipeline State

retries
PipelineState.scala
Replay: real traced execution (multi-file project)
object Main {
  def main(args: Array[String]): Unit = {
    val retries = 1
    var stage = "queued"
    var attempts = 0

    stage = "started"
    attempts = attempts + 1

    if (retries > 0) {
      attempts = attempts + retries
    }

    val success = attempts <= 2
    if (success) {
      stage = "complete"
    } else {
      stage = "retry-later"
    }

    println("attempts=" + attempts)
    println("stage=" + stage)
  }
}
object Main {
  def main(args: Array[String]): Unit = {
    val retries = 0
    var stage = "queued"
    var attempts = 0

    stage = "started"
    attempts = attempts + 1

    if (retries > 0) {
      attempts = attempts + retries
    }

    val success = attempts <= 2
    if (success) {
      stage = "complete"
    } else {
      stage = "retry-later"
    }

    println("attempts=" + attempts)
    println("stage=" + stage)
  }
}
object Main {
  def main(args: Array[String]): Unit = {
    val retries = 2
    var stage = "queued"
    var attempts = 0

    stage = "started"
    attempts = attempts + 1

    if (retries > 0) {
      attempts = attempts + retries
    }

    val success = attempts <= 2
    if (success) {
      stage = "complete"
    } else {
      stage = "retry-later"
    }

    println("attempts=" + attempts)
    println("stage=" + stage)
  }
}
  1. retries ← 1, stage ← queued, attempts ← 0

    1object Main {2  def main(args: Array[String]): Unit = {3    val retries→ 1 = 1 //@retries=0, 24    var stage→ queued = "queued"5    var attempts→ 0 = 067    stage→ started = "started"8    attempts→ 1 = attempts + 1910    if (retries > 0) {
  2. attempts ← 2

    10if (retries1 > 0) {11  attempts→ 2 = attempts + retries112}
  3. success ← true

    14val success→ true = attempts2 <= 215if (success) {16  stage = "complete"
  4. stage ← complete

    14val success = attempts <= 215if (successtrue) {16  stage→ complete = "complete"17} else {18  stage = "retry-later"
  5. println("attempts=" + attempts)

    21    println("attempts=" + attempts2)22    println("stage=" + stagecomplete)23  }24}
    outputattempts=2
    stage=complete
  1. retries ← 0, stage ← queued, attempts ← 0, success ← true

    1object Main {2  def main(args: Array[String]): Unit = {3    val retries→ 0 = 04    var stage→ queued = "queued"5    var attempts→ 0 = 067    stage→ started = "started"8    attempts→ 1 = attempts + 1910    if (retries > 0) {11      attempts = attempts + retries12    }1314    val success→ true = attempts1 <= 215    if (success) {16      stage = "complete"
  2. stage ← complete

    14val success = attempts <= 215if (successtrue) {16  stage→ complete = "complete"17} else {18  stage = "retry-later"
  3. println("attempts=" + attempts)

    21    println("attempts=" + attempts1)22    println("stage=" + stagecomplete)23  }24}
    outputattempts=1
    stage=complete
  1. retries ← 2, stage ← queued, attempts ← 0

    1object Main {2  def main(args: Array[String]): Unit = {3    val retries→ 2 = 24    var stage→ queued = "queued"5    var attempts→ 0 = 067    stage→ started = "started"8    attempts→ 1 = attempts + 1910    if (retries > 0) {
  2. attempts ← 3

    10if (retries2 > 0) {11  attempts→ 3 = attempts + retries212}
  3. success ← false

    14val success→ false = attempts3 <= 215if (success) {16  stage = "complete"
  4. stage ← retry-later

    16  stage = "complete"17} else {18  stage→ retry-later = "retry-later"19}
  5. println("attempts=" + attempts)

    21    println("attempts=" + attempts3)22    println("stage=" + stageretry-later)23  }24}
    outputattempts=3
    stage=retry-later