-1

I have n number of goroutines waiting on a task channel. These goroutines are responsible for performing these tasks. Currently, I'm using beego as my web golang framework. When do I signal termination to my goroutines in a beego application? How do I deduce when a service termination request is received?

ABAA
  • 101
  • 1
  • 12

1 Answers1

2

As a first step, let's create a channel and bind it to signal which is in your sphere of interest. Then you need to create context and trigger cancelation function when you will receive this signal.

c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
ctx, cancel := context.WithCancel(context.Background()) // pass your ctx in all goroutines as first argument, 
go func() {
    signal := <-c
    logger.Info("signal was received", zap.Stringer("signal", signal)
    cancel()
}()

Then, you can create WaitGroup and pass your context as first argument in every goroutine

wg := &sync.WaitGroup{}
hooks.RunStartHooks(ctx, wg)

Inside your worker listen to context cancelation working appropriately with wg as specified in docs

for {

    select {

    case <-ctx.Done():
        wg.Done()
        return
    }

    // other cases
}

And finally,

    timeout := cfg.Server.HooksCloseTimeout // this is from your config 
    if waitTimeout(wg, timeout) {
        logger.Info("timed out waiting for wait group")
    } else {
        logger.Info("server exited properly")
    }

where waitTimeout is

// waitTimeout waits for the waitgroup for the specified max timeout.
// Returns true if waiting timed out.
func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
    c := make(chan struct{})
    go func() {
        defer close(c)
        wg.Wait()
    }()
    select {
    case <-c:
        return false // completed normally
    case <-time.After(timeout):
        return true // timed out
    }
}
Oleg
  • 662
  • 6
  • 10