Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute task based on dependencies in Go

Tags:

logic

go

I think this more of a question about logic than go itself. I want to find a way to execute a task based on its dependencies in go language.

Task Workflow

Considering the workflow above: Task 1,2,3 and 4 can be ran asynchronously at the same time. Task 10 will be executed when Task 1 and 2 is finished. Task 11 will be executed when Task 3 and 4 is finished Task 12 will be executed when Task 11 and 12 is finished Task 100 will be executed when Task 10 and 11 is finished.

I'm using go channels to make the concurrent executions and want to find an effective way to control the dependencies. I know I could have some sort of flag and a table to control execution but ideally I would like to do it in memory to avoid the database calls to control such thing. I also understand that there are several ways of doing this, but would like to hear your ideas because I'm sure there is a better way of doing than the ways I could come up with so far.

like image 849
Jose Bagatelli Avatar asked Jul 11 '14 05:07

Jose Bagatelli


1 Answers

There was an interesting reddit thread on that topic, in response to the article "How to Wait for All Goroutines to Finish Executing Before Continuing".

The correct article is "How to Wait for All Goroutines to Finish Executing Before Continuing, Part Two: Fixing My Oops" and illustrates several ways to wait for goroutines before carrying on with another task.

Depending on the kind of information you have for the tasks to synchronize, sync.WaitGroup is a good candidate (as in this example).

But:

When you know the number of messages to expect you might as well count them to know when to finish. Here the WaitGroup is superfluous and confusing.

This would block until all 3 messages are received:

func main() {
  messages := make(chan int)
  go func() {
      time.Sleep(time.Second * 3)
      messages <- 1
  }()
  go func() {
      time.Sleep(time.Second * 2)
      messages <- 2
  }()
  go func() {
      time.Sleep(time.Second * 1)
      messages <- 3
  }()
  for i := 0; i < 3; i++ {
      fmt.Println(<-messages)
  }
}

So it really depends on what you know from the tasks you are waiting for.

like image 91
VonC Avatar answered Sep 30 '22 03:09

VonC