How to kill the console input when process interrupted

139 Views Asked by At

I'm playing with Scalaz Stream library and trying to create a simple console app.

I followed the tutorial scalaz streams and they have an example with console read and write.

But I faced with a strange problem which I'm not sure how to sort out.

This is my code:

import scala.concurrent.duration._
import scalaz.concurrent.Task

object StreamApp extends App {

  (new StreamExec).go3
}

class StreamExec {

  def gets: Task[String] = Task {
    scala.io.StdIn.readLine()
  }

  def puts(ln: String, answer: String): Task[Boolean] = Task {
    println(ln)
    ln.contains(answer)
  }

  def go3 {

    import scalaz.stream.Process

    val q = Seq("1", "2", "3") map { case p =>

      println(s"Say $p")

      val in = Process eval gets

      val out = in flatMap { line =>
        Process eval puts(line, p)
      }

      out.runLog.attemptRunFor(5.seconds)
    }

    println(q)
  }
}

When I run it the output looks like this

background log: info: Say 1
1
background log: info: 1
background log: info: Say 2
background log: info: Say 3
3
3
background log: info: 3
background log: info: List(\/-(Vector(true)), -\/(java.util.concurrent.TimeoutException), \/-(Vector(true)))

1 was fine, 2 failed by timeout after 5 sec, and then 3 requires input twice.

The problem is that when the Process fail on time the console input is not unblocked (not killed) and still waiting for the user's input.

I've tried to reproduce it with futures and faced with the same problem.

Thank you.

1

There are 1 best solutions below

0
On

Usually in scalaz stream, you get (acquire the value) then process it and terminate.

In this example, if your processing is just read an print, you don't need runLog hence what you want are just arbitrary effects to be processed.

I think this code may help

eval(gets)
.flatMap { name =>   Process(1,2,3).flatMap( ln => eval(puts(ln,name))) }
.take(3)
.run.run

What you really need is to pick one of the Process1 combinators to pipe your process through and that will eventually terminate your program. You can experiment with various combinators available to build your program.