pull/2481/head
FengbinShi 2 years ago
parent 639d47e89f
commit b9acf8fbbf
  1. 39
      health/checker.go
  2. 24
      health/health.go
  3. 24
      health/health_test.go

@ -10,37 +10,48 @@ type Checker interface {
Check(ctx context.Context) (interface{}, error) Check(ctx context.Context) (interface{}, error)
} }
type Watcher interface { type Notifier interface {
Watch(string) notify(string)
} }
type checker struct { type CheckerHandler interface {
setNotifier(w Notifier)
run(ctx context.Context)
getStatus() CheckerStatus
getName() string
}
type checkerHandler struct {
Name string Name string
intervalTime time.Duration intervalTime time.Duration
timeout time.Duration timeout time.Duration
Checker Checker
CheckerStatus CheckerStatus
*sync.RWMutex *sync.RWMutex
Watcher Notifier
} }
func NewChecker(name string, ch Checker, interval, timeout time.Duration) *checker { func NewChecker(name string, ch Checker, interval, timeout time.Duration) CheckerHandler {
return &checker{ return &checkerHandler{
Name: name, Name: name,
intervalTime: interval, intervalTime: interval,
timeout: timeout, timeout: timeout,
Checker: ch, Checker: ch,
CheckerStatus: CheckerStatus{}, CheckerStatus: CheckerStatus{},
RWMutex: &sync.RWMutex{}, RWMutex: &sync.RWMutex{},
Watcher: nil, Notifier: nil,
} }
} }
func (c *checker) setWatcher(w Watcher) { func (c *checkerHandler) setNotifier(w Notifier) {
c.Watcher = w c.Notifier = w
}
func (c *checkerHandler) getName() string {
return c.Name
} }
func (c *checker) check(ctx context.Context) bool { func (c *checkerHandler) check(ctx context.Context) bool {
defer func() { defer func() {
recover() recover()
}() }()
@ -71,7 +82,7 @@ func (c *checker) check(ctx context.Context) bool {
return true return true
} }
func (c *checker) run(ctx context.Context) { func (c *checkerHandler) run(ctx context.Context) {
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
@ -80,15 +91,15 @@ func (c *checker) run(ctx context.Context) {
} }
if c.check(ctx) { if c.check(ctx) {
//notify //notify
if c.Watcher != nil { if c.Notifier != nil {
c.Watcher.Watch(c.Name) c.Notifier.notify(c.Name)
} }
} }
time.Sleep(c.intervalTime) time.Sleep(c.intervalTime)
} }
} }
func (c *checker) getStatus() CheckerStatus { func (c *checkerHandler) getStatus() CheckerStatus {
c.RLock() c.RLock()
defer c.RUnlock() defer c.RUnlock()
return c.CheckerStatus return c.CheckerStatus

@ -6,7 +6,7 @@ import (
) )
type CheckerMgr struct { type CheckerMgr struct {
checkers map[string]*checker checkers map[string]CheckerHandler
ctx context.Context ctx context.Context
cancel func() cancel func()
watchers map[uint64]chan string watchers map[uint64]chan string
@ -18,7 +18,7 @@ type CheckerMgr struct {
func New(ctx context.Context) *CheckerMgr { func New(ctx context.Context) *CheckerMgr {
c, cancel := context.WithCancel(ctx) c, cancel := context.WithCancel(ctx)
return &CheckerMgr{ return &CheckerMgr{
checkers: make(map[string]*checker), checkers: make(map[string]CheckerHandler),
ctx: c, ctx: c,
cancel: cancel, cancel: cancel,
lock: sync.RWMutex{}, lock: sync.RWMutex{},
@ -53,7 +53,7 @@ func (c *CheckerMgr) GetStatus(name ...string) []StatusResult {
if len(name) == 0 { if len(name) == 0 {
for _, v := range c.checkers { for _, v := range c.checkers {
status = append(status, StatusResult{ status = append(status, StatusResult{
Name: v.Name, Name: v.getName(),
CheckerStatus: v.getStatus(), CheckerStatus: v.getStatus(),
}) })
} }
@ -61,7 +61,7 @@ func (c *CheckerMgr) GetStatus(name ...string) []StatusResult {
for _, n := range name { for _, n := range name {
if v, ok := c.checkers[n]; ok { if v, ok := c.checkers[n]; ok {
status = append(status, StatusResult{ status = append(status, StatusResult{
Name: v.Name, Name: v.getName(),
CheckerStatus: v.getStatus(), CheckerStatus: v.getStatus(),
}) })
} }
@ -70,12 +70,12 @@ func (c *CheckerMgr) GetStatus(name ...string) []StatusResult {
return status return status
} }
func (c *CheckerMgr) RegisterChecker(checker2 *checker) { func (c *CheckerMgr) RegisterChecker(checker CheckerHandler) {
c.checkers[checker2.Name] = checker2 c.checkers[checker.getName()] = checker
checker2.setWatcher(c) checker.setNotifier(c)
} }
func (c *CheckerMgr) Watch(name string) { func (c *CheckerMgr) notify(name string) {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() defer c.lock.RUnlock()
for _, ch := range c.watchers { for _, ch := range c.watchers {
@ -86,24 +86,24 @@ func (c *CheckerMgr) Watch(name string) {
} }
} }
type WatcherResult struct { type Watcher struct {
id uint64 id uint64
Ch <-chan string Ch <-chan string
c *CheckerMgr c *CheckerMgr
} }
func (w *WatcherResult) Close() { func (w *Watcher) Close() {
w.c.closeWatcher(w.id) w.c.closeWatcher(w.id)
} }
func (c *CheckerMgr) NewWatcher() WatcherResult { func (c *CheckerMgr) NewWatcher() Watcher {
c.lock.Lock() c.lock.Lock()
wID := c.watcherID wID := c.watcherID
c.watcherID++ c.watcherID++
ch := make(chan string, 1) ch := make(chan string, 1)
c.watchers[wID] = ch c.watchers[wID] = ch
c.lock.Unlock() c.lock.Unlock()
return WatcherResult{ return Watcher{
id: wID, id: wID,
Ch: ch, Ch: ch,
c: c, c: c,

@ -3,7 +3,6 @@ package health
import ( import (
"fmt" "fmt"
"golang.org/x/net/context" "golang.org/x/net/context"
"math/rand"
"testing" "testing"
"time" "time"
) )
@ -13,9 +12,9 @@ type A struct {
func (A) Check(ctx context.Context) (interface{}, error) { func (A) Check(ctx context.Context) (interface{}, error) {
fmt.Println("check A") fmt.Println("check A")
if rand.Int()%2 == 0 { //if rand.Int()%2 == 0 {
return "出错A", fmt.Errorf("错误:%s", "123") // return "出错A", fmt.Errorf("错误:%s", "123")
} //}
return "正常A", nil return "正常A", nil
} }
@ -24,20 +23,19 @@ type B struct {
func (B) Check(ctx context.Context) (interface{}, error) { func (B) Check(ctx context.Context) (interface{}, error) {
fmt.Println("check B") fmt.Println("check B")
if rand.Int()%2 == 0 { //if rand.Int()%2 == 0 {
return "出错B", fmt.Errorf("错误:%s", "123B") // return "出错B", fmt.Errorf("错误:%s", "123B")
} //}
return "正常B", nil return "正常B", nil
} }
func TestNew(t *testing.T) { func TestNew(t *testing.T) {
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
cm := New(ctx) cm := New(ctx)
cm.RegisterChecker(NewChecker("A", A{}, 0, time.Second*10)) cm.RegisterChecker(NewChecker("A", A{}, time.Second*0, time.Second*10))
cm.RegisterChecker(NewChecker("B", B{}, 0, time.Second*10)) cm.RegisterChecker(NewChecker("B", B{}, time.Second*0, time.Second*10))
cm.Start() cm.Start()
go func() { go func() {
s := cm.GetStatus() s := cm.GetStatus()
fmt.Println("----", s) fmt.Println("----", s)
w := cm.NewWatcher() w := cm.NewWatcher()
@ -45,8 +43,10 @@ func TestNew(t *testing.T) {
for i := range w.Ch { for i := range w.Ch {
fmt.Println("---", cm.GetStatus(i)) fmt.Println("---", cm.GetStatus(i))
} }
}() }()
time.Sleep(time.Second * 100) time.Sleep(time.Second * 20)
cm.Stop()
t.Log("-----=")
time.Sleep(time.Second * 5)
cancel() cancel()
} }

Loading…
Cancel
Save