Documentation ¶
Overview ¶
Package cancelgroup provides a mechanism to coordinate related tasks of goroutines and associate them with a cancelable context.
The errgroup package is very useful for coordinating groups of goroutines and limiting the number of active goroutines, and will allow other goroutines to coordinate based on a context created by the error Group. However, there is no way to supply a parent context which can cancel the Group, and the Group's `Wait()` method blocks until all goroutines are complete even when a routine fails and sets the Group's error.
The Group in this package guarantees that Wait will return immediately when the Group's context is canceled. It also provides a mechanism to schedule tasks which accept an incoming context, allowing those tasks to cleanly exit if the Group is canceled.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrorGroupCanceled = errors.New("Group canceled")
ErrorGroupCanceled is returned from the Wait or ContextCause methods of a Group when the Group's Cancel method is called.
var ErrorParentContextCanceled = errors.New("Group parent context was canceled")
ErrorParentContextCanceled is returned from the Wait or ContextCause methods of a Group which was aborted due to its parent context being canceled.
Functions ¶
This section is empty.
Types ¶
type CoordinatedTask ¶
CoordinatedTask represents a Task which is capable of monitoring a context and cleanly exiting if the context is canceled prior to the Task's execution.
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
Group provides synchronization and cancellation for related goroutines working on a shared task.
func New ¶
func New() *Group
New creates a new Group. If the calling code needs the ability to cancel a long-running Group, use NewWithContext and pass in a parent context for which the calling routine owns a context.CancelFunc or context.CancelCauseFunc.
func NewWithContext ¶
NewWithContext creates a new Group and derives a new context from the given Context. If the parent context is canceled, the Group's context will also be canceled.
When all tasks run inside the returning Group are complete, the Context will be completed. The Group context's casuse will be nil if all tasks completed successfully, otherwise it will contain the first error returned by a Group task.
func (*Group) Co ¶ added in v1.1.0
func (g *Group) Co(t CoordinatedTask)
Co adds the given CoordinatedTask to the Group and starts it on a new goroutine, passing in the Group's context. A CoordinatedTask **MUST** monitor ctx.Done() and exit as soon as possible once detecting the context is canceled.
Example ¶
Co schedules a CoordinatedTask on the Group. Coordinated tasks are simply functions which accept a context.Context as their only parameter, and are expected to exit gracefully as soon as possible after the context is canceled.
package main import ( "context" "fmt" "github.com/Kintar/cancelgroup" "time" ) func main() { g := cancelgroup.New() g.Co(func(ctx context.Context) error { <-ctx.Done() return nil }) g.Go(func() error { <-time.After(time.Millisecond * 250) g.Cancel() return nil }) fmt.Println(g.Wait()) }
Output:
func (*Group) Go ¶
Go adds the given Task to the Group and starts it on a new goroutine. Since a Task does not accept a context, Tasks will continue to run until their natural termination even if the Group is canceled.
Example ¶
Go schedules a Task on the Group. Tasks are simple functions which return an error, but are not capable of exiting based on the Done status of a context.Context. They will continue to run even after a Group is canceled, but will not affect the value returned by Group.Wait().
package main import ( "errors" "fmt" "github.com/Kintar/cancelgroup" "sync" "time" ) func main() { g := cancelgroup.New() errTaskCompleted := errors.New("task completed") // a sync.WaitGroup so we can coordinate the final message of this example with the completion of our scheduled Task var wg sync.WaitGroup wg.Add(1) // track the start time of our Group start := time.Now() g.Go(func() error { defer wg.Done() <-time.After(time.Millisecond * 250) return errTaskCompleted }) // cancel the Group so that Wait returns immediately g.Cancel() // read the error err := g.Wait() // track the time the Group.Wait call completed waitCompleteAt := time.Now() fmt.Println("wait completed in", waitCompleteAt.Sub(start).Milliseconds(), "ms") // err will be ErrorGroupCanceled, not errTaskCompleted fmt.Println("Group error is: ", err) // Now wait for the scheduled task to finish wg.Wait() taskCompleteAt := time.Now() fmt.Println("task completed in", taskCompleteAt.Sub(start).Milliseconds(), "ms") // err will be ErrorGroupCanceled, not errTaskCompleted fmt.Println("Group error is: ", err) }
Output:
func (*Group) Wait ¶
Wait will block the calling goroutine until this Group's tasks have all completed successfully, or until the Group's context is canceled due to a child task error or the parent context's completion, whichever happens first. Once Wait returns, further calls will be non-blocking and will return the same value.
type Task ¶
type Task func() error
Task represents a function which will be run inside a Group, but which is not capable of coordinating its work on a context.Context. A Task which is run in a Group will continue to run until it naturally terminates, even if the Group or its parent context is canceled.