mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			44 lines
		
	
	
		
			924 B
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			44 lines
		
	
	
		
			924 B
		
	
	
	
		
			Go
		
	
	
	
| package util
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"sync"
 | |
| )
 | |
| 
 | |
| // 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 errors.Join(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
 | |
| }
 |