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 }