README

WaitGroup

GoDoc Go ReportCard

A simple wrapper around sync.WaitGroup with support for specifying a timeout to return in bounded time, e.g. during shutdown.

For convenience two additional functions are provided in case existing sync.WaitGroup or errgroup.Group should be used directly instead of wrapping.

Why would I want this?

In case you use sync.WaitGroup ("wg") to manage goroutines you might run into an issue where wg.Wait() could block very long, err... forever, if one or more goroutines do not finish their work in time/livelock, e.g. due to a missing wg.Done(). ¯\_(ツ)_/¯

How to use

Example with waitgroup.WaitGroup{}

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/embano1/waitgroup"
)

func main() {
	var wg waitgroup.WaitGroup

	wg.Add(1)
	go func() {
		defer wg.Done()
		fmt.Println("I'm slow")
		time.Sleep(time.Second * 5)
	}()

	if err := wg.WaitTimeout(time.Second); err != nil {
		fmt.Printf("an error occurred: %v\n", err)
		os.Exit(1)
	}
}

Run this program:

go run cmd/main.go
I'm slow
an error occurred: timed out
exit status 1

Example with waitgroup.Await()

package main

import (
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/embano1/waitgroup"
)

func main() {
	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		defer wg.Done()
		time.Sleep(time.Second * 5)
	}()

	if err := waitgroup.Await(&wg, time.Second); err != nil {
		fmt.Printf("an error occurred: %v\n", err)
		os.Exit(1)
	}
}

Run this program:

go run cmd/main.go
I'm slow
an error occurred: timed out
exit status 1

See GoDoc for more API details and more examples.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrTimeout = errors.New("timed out")

    ErrTimeout is returned when the timeout in WaitTimeout is exceeded

    Functions

    func Await

    func Await(wf Waiter, timeout time.Duration) error

      Await is a convenience function that can be used instead of WaitGroup provided by this package. Await blocks until Waiter returns or the specified timeout is exceeded. In case of timeout exceeded the error ErrTimeout is returned and the internally spawned goroutine might leak if Waiter never returns.

      It is safe to call Await concurrently and multiple times but doing so might leak additional goroutines as described above.

      Example
      Output:
      
      timed out
      

      func AwaitWithError

      func AwaitWithError(we WaitErrorer, timeout time.Duration) error

        AwaitWithError is a convenience function that can be used instead of WaitGroup provided by this package. AwaitWithError blocks until WaitErrorer returns or the specified timeout is exceeded. Any error from WaitErrorer will be returned unless the timeout has been exceeded before. In case of timeout exceeded the error ErrTimeout is returned and the internally spawned goroutine might leak if WaitErrorer never returns.

        It is safe to call AwaitWithError concurrently and multiple times but doing so might leak additional goroutines as described above.

        Example (Error)
        Output:
        
        did not work
        
        Example (Timeout)
        Output:
        
        timed out
        

        Types

        type WaitErrorer

        type WaitErrorer interface {
        	Wait() error
        }

          WaitErrorer is the interface blocking on Wait() and returning any error that occurred from Wait(). errgroup.Group implements this interface.

          type WaitGroup

          type WaitGroup struct {
          	sync.WaitGroup
          }

            WaitGroup wraps sync.WaitGroup and adds a method WaitTimeout to abort waiting for long-running, blocked or leaked goroutines blocking Wait() from the underlying WaitGroup. A caller might use this functionality to terminate a program in a bounded time.

            func (*WaitGroup) WaitTimeout

            func (wg *WaitGroup) WaitTimeout(timeout time.Duration) error

              WaitTimeout blocks until the WaitGroup counter is zero or when timeout is exceeded. It spawns an internal goroutine. In case of timeout exceeded the error ErrTimeout is returned and the internally spawned goroutine might leak if the underlying WaitGroup never returns.

              It is safe to call WaitTimeout concurrently but doing so might leak additional goroutines as described above.

              Example
              Output:
              
              timed out
              

              type Waiter

              type Waiter interface {
              	Wait()
              }

                Waiter is the interface blocking on Wait(). sync.WaitGroup implements this interface.

                Source Files