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.
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
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.