github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/health/checks/context_check.go (about)

     1  package checks
     2  
     3  import (
     4  	"context"
     5  	"runtime"
     6  	"sync/atomic"
     7  )
     8  
     9  type contextCheck struct {
    10  	name       string
    11  	terminated uint32 // TODO: When the minimal supported base go version is 1.19, use atomic.Bool
    12  	ctx        context.Context
    13  	Error      error
    14  }
    15  
    16  func CheckContextStatus(ctx context.Context, name ...string) error {
    17  	check := NewContextCheck(ctx, name...)
    18  	return check.checkstatus()
    19  }
    20  
    21  func NewContextCheck(ctx context.Context, name ...string) *contextCheck {
    22  	if len(name) > 1 {
    23  		panic("context check does only accept one name")
    24  	}
    25  	if ctx == nil {
    26  		panic("context check needs a context")
    27  	}
    28  
    29  	contextName := "Unknown"
    30  	if len(name) == 1 {
    31  		contextName = name[0]
    32  	} else {
    33  		pc, _, _, ok := runtime.Caller(1)
    34  		details := runtime.FuncForPC(pc)
    35  		if ok && details != nil {
    36  			contextName = details.Name()
    37  		}
    38  	}
    39  
    40  	c := contextCheck{
    41  		name:  contextName,
    42  		ctx:   ctx,
    43  		Error: nil,
    44  	}
    45  
    46  	go func() {
    47  		<-ctx.Done()
    48  		atomic.StoreUint32(&c.terminated, 1)
    49  	}()
    50  
    51  	return &c
    52  }
    53  
    54  func (c *contextCheck) checkstatus() error {
    55  	v := atomic.LoadUint32(&c.terminated)
    56  	if v == 1 {
    57  		c.Error = c.ctx.Err()
    58  		return c.Error
    59  	}
    60  	return nil
    61  }
    62  
    63  func (c *contextCheck) Name() string {
    64  	return c.name
    65  }