parent
0536c38150
commit
4d2fb959c5
@ -0,0 +1,73 @@ |
||||
package health |
||||
|
||||
import ( |
||||
"context" |
||||
"sync" |
||||
"time" |
||||
) |
||||
|
||||
type Checker interface { |
||||
Check(ctx context.Context) (interface{}, error) |
||||
} |
||||
|
||||
type Watcher func(string) |
||||
|
||||
type checker struct { |
||||
Name string |
||||
intervalTime time.Duration |
||||
timeout time.Duration |
||||
Checker |
||||
CheckerStatus |
||||
sync.RWMutex |
||||
Watcher |
||||
} |
||||
|
||||
func NewChecker(name string, checker Checker) { |
||||
|
||||
} |
||||
|
||||
func (c *checker) check(ctx context.Context) bool { |
||||
defer func() { |
||||
recover() |
||||
}() |
||||
ctx, cancel := context.WithTimeout(ctx, c.timeout) |
||||
defer cancel() |
||||
detail, err := c.Check(ctx) |
||||
status := StatusUp |
||||
if err != nil { |
||||
status = StatusDown |
||||
} |
||||
c.Lock() |
||||
defer c.Unlock() |
||||
old := c.CheckerStatus |
||||
c.CheckerStatus = CheckerStatus{ |
||||
Status: status, |
||||
Detail: detail, |
||||
Err: err, |
||||
} |
||||
if c.CheckerStatus == old { |
||||
return false |
||||
} |
||||
return true |
||||
} |
||||
|
||||
func (c *checker) run(ctx context.Context) { |
||||
for { |
||||
select { |
||||
case <-ctx.Done(): |
||||
return |
||||
default: |
||||
} |
||||
if c.check(ctx) { |
||||
//发送改变通知
|
||||
c.Watcher(c.Name) |
||||
} |
||||
time.Sleep(c.intervalTime) |
||||
} |
||||
} |
||||
|
||||
func (c *checker) getStatus() CheckerStatus { |
||||
c.RLock() |
||||
defer c.RUnlock() |
||||
return c.CheckerStatus |
||||
} |
@ -0,0 +1,63 @@ |
||||
package health |
||||
|
||||
import ( |
||||
"golang.org/x/net/context" |
||||
) |
||||
|
||||
type CheckerMgr struct { |
||||
checkers map[string]checker |
||||
ctx context.Context |
||||
cancel func() |
||||
watchers []chan string |
||||
} |
||||
|
||||
func New(ctx context.Context) *CheckerMgr { |
||||
c, cancel := context.WithCancel(ctx) |
||||
return &CheckerMgr{ |
||||
checkers: make(map[string]checker), |
||||
ctx: c, |
||||
cancel: cancel, |
||||
} |
||||
} |
||||
|
||||
func (c *CheckerMgr) Start() { |
||||
for _, v := range c.checkers { |
||||
go func() { |
||||
v.run(c.ctx) |
||||
}() |
||||
} |
||||
} |
||||
|
||||
func (c *CheckerMgr) Stop() { |
||||
c.cancel() |
||||
} |
||||
|
||||
type StatusResult struct { |
||||
Name string |
||||
CheckerStatus |
||||
} |
||||
|
||||
// GetStatus
|
||||
//
|
||||
// if name is nil return all status
|
||||
func (c *CheckerMgr) GetStatus(name ...string) []StatusResult { |
||||
status := make([]StatusResult, 0, len(name)) |
||||
if len(name) == 0 { |
||||
for _, v := range c.checkers { |
||||
status = append(status, StatusResult{ |
||||
Name: v.Name, |
||||
CheckerStatus: v.getStatus(), |
||||
}) |
||||
} |
||||
} else { |
||||
for _, n := range name { |
||||
if v, ok := c.checkers[n]; ok { |
||||
status = append(status, StatusResult{ |
||||
Name: v.Name, |
||||
CheckerStatus: v.getStatus(), |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
return status |
||||
} |
@ -0,0 +1,14 @@ |
||||
package health |
||||
|
||||
type Status int |
||||
|
||||
const ( |
||||
StatusDown Status = iota |
||||
StatusUp |
||||
) |
||||
|
||||
type CheckerStatus struct { |
||||
Status |
||||
Detail interface{} |
||||
Err error |
||||
} |
Loading…
Reference in new issue