InitEnabler
InitEnabler

Reputation: 63

Best way to implement trackable concurrency in Golang

So I've been writing a small toy program to run simple tasks like Jenkins does. Some features this program has are:

I've been following this tutorial using goroutines to pull stuff out of a channel and process them. However I keep running into the problem of how would I implement canceling of certain goroutines that already processing a job. For example:

I have 5 jobs in a queue and 2 executors (Executor A and Executor B). Both executors pull one job off the queue and process. However, I want to have Executor B stop its processing of it's current job and pull the next job off the queue.

It seems that goroutines can't really be tracked in terms of "goroutine A... B... C..." and it seems not to be best practice to implement that sort of logic. With that being said is there any pattern out there that would solve my use case?

Upvotes: 0

Views: 481

Answers (1)

Burak Serdar
Burak Serdar

Reputation: 51572

One of the ways to cancel processing in a goroutine is to use a cancelable context: context.WithCancel. That gives you a context and a cancel function which you can use to notify a goroutine that it is canceled. The goroutine should periodically check for the context and terminate if it is canceled.

You can track goroutines using their contexts. For each goroutine you create, you can create a cancelable context, and keep the context and the cancel function in a list/map that holds your running tasks. Then your goroutines will look like this:

func executor(ctx context.Context) {
  for {
     // Do stuff
     select {
       case <-ctx.Done():
           // terminate
       default:
     }
    // Do more stuff
  }
}

You have to poll the context every now and then to see if it was canceled.

And you start a goroutine like this:

go func() {
   ctx, cancel:=context.WithCancel(context.Background())
   defer cancel()
   // Store ctx and cancel in a map if you need to
   executor(ctx)
   // Remove stored context
}()

When you need to cancel a running goroutine, call its cancel function, and it'll terminate eventually.

Upvotes: 0

Related Questions