Hopac timeOutMillis does not work as expected

87 views Asked by At

I recently started playing with Hopac and think that this is just awesome. Here is, however a problem that I cannot wrap my head around. Below is the code snippet:

let rnd = new Random()

let logger (msg:string) =
    let c = Ch<string>()
    let msgLoop = job {
        for i in [1..15] do 
            let msgStr = sprintf "%s %d" msg i
            do! timeOutMillis (rnd.Next(1000,3000))
            do! c *<- msgStr
    }
    printfn "Started job %s" msg 
    msgLoop |> start
    c

let timeout = timeOutMillis 3000

let c = logger "Instance Foo"
let rec printLoop () = Job.delay <| fun () -> 
    Alt.choose[
            timeout ^=> fun () -> printfn "job timed out"
                                  Job.result ()
            Ch.take c ^=> fun msg -> printfn "Log: %s" msg
                                     printLoop ()
    ]
printLoop () |> start

I supposed that after 3000 msec is elapsed timeout alternative will become available and will abort printing messages. This is not happening, and timeout gets fired only when nothing is left in channel c.

I placed timeout at the first placein Alt.choose list since as per documentation if multiple alternatives are available at the same time, the one which appears first in the list gets picked (On the Semantics of Alternatives)

Any help is highly appreciated

1

There are 1 answers

1
user7099105 On BEST ANSWER

Here is a quick answer. The timeout is not started on the line:

let timeout = timeOutMillis 3000

Rather, the timeout is (re)started on the line

 timeout ^=> fun () -> printfn "job timed out"

every time the line is evaluated. The shortest fix to the program would be to change the line where you define the timeout as:

let timeout = timeOutMillis 3000 |> memo