Reputation: 333
I have a goroutine for a long running job. When the job is done, it pushes the results to a channel. In the meantime, while the job is running, I want to keep updating an API with the status RUNNING.
So far, I have the following code :
func getProgressTimeout() <-chan time.Time {
return time.After(5 * time.Minute)
}
func runCommand(arg *Request) {
chanResult := make(chan Results)
go func(args *Request, c chan Results) {
resp, err := execCommand(args)
c <- Results{
resp: resp,
err: err,
}
}(arg, chanResult)
var err error
progressLoop:
for {
select {
case <-getProgressTimeout():
updateProgress() // this method will send status= RUNNING to a REST API
case out := <-chanResult:
err = jobCompleted(request, out)
break progressLoop
}
}
return err
}
I am new to golang. And I have reached the above code after lot of trial and error, and googling. It's working now. Still it doesn't feel intuitive to me when I look at it (this may very well be because, I am still trying to learn the Go way of doing things). So my question is, can I refactor this into better shape? Is there some existing pattern which is applicable in this kind of scenario? Or if there is some totally different approach to keep sending periodic updates while job is running?
Also, any suggestions to improve upon my golang concurrency are also appreciated. :)
Thanks in advance!
Upvotes: 3
Views: 1226
Reputation: 273366
Consider using time.NewTicker, which sends a periodic value to a channel. Here's an example from the documentation:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
done := make(chan bool)
go func() {
time.Sleep(10 * time.Second)
done <- true
}()
for {
select {
case <-done:
fmt.Println("Done!")
return
case t := <-ticker.C:
fmt.Println("Current time: ", t)
}
}
}
Note that the embedded goroutine invoking func
emulates a long task by sleeping for 10 seconds, while the caller uses select
to wait for the result, while also receiving periodic events from the ticker - this is where you can do the API progress update.
Upvotes: 4