Revision 313c88f3e1fbf009d67d2e6578deb9b9fa4e4f08 authored by Guilherme Caulada on 18 October 2022, 01:11:59 UTC, committed by GitHub on 18 October 2022, 01:11:59 UTC
1 parent 7f5914f
Raw File
contextutil.go
package util

import (
	"context"
	"sync"

	"github.com/hashicorp/go-multierror"
)

// this is a decorator for a regular context that contains a custom error and returns the
type contextWithCancellableReason struct {
	context.Context
	mtx sync.Mutex
	err error
}

func (c *contextWithCancellableReason) Err() error {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if c.err != nil {
		return multierror.Append(c.Context.Err(), c.err)
	}
	return c.Context.Err()
}

type CancelCauseFunc func(error)

// WithCancelCause creates a cancellable context that can be cancelled with a custom reason
func WithCancelCause(parent context.Context) (context.Context, CancelCauseFunc) {
	ctx, cancel := context.WithCancel(parent)
	errOnce := sync.Once{}
	result := &contextWithCancellableReason{
		Context: ctx,
	}
	cancelFn := func(reason error) {
		errOnce.Do(func() {
			result.mtx.Lock()
			result.err = reason
			result.mtx.Unlock()
			cancel()
		})
	}
	return result, cancelFn
}
back to top