You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
2.0 KiB
122 lines
2.0 KiB
package health
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Checker interface {
|
|
Check(ctx context.Context) (interface{}, error)
|
|
}
|
|
|
|
type Notifier interface {
|
|
notify(string)
|
|
}
|
|
|
|
type CheckerHandler interface {
|
|
setNotifier(w Notifier)
|
|
run(ctx context.Context)
|
|
getStatus() CheckerStatus
|
|
getName() string
|
|
}
|
|
|
|
type checkerHandler struct {
|
|
Name string
|
|
intervalTime time.Duration
|
|
timeout time.Duration
|
|
Checker
|
|
CheckerStatus
|
|
*sync.RWMutex
|
|
Notifier
|
|
}
|
|
|
|
func NewChecker(name string, ch Checker, opt ...CheckOption) CheckerHandler {
|
|
c := &checkerHandler{
|
|
Name: name,
|
|
Checker: ch,
|
|
CheckerStatus: CheckerStatus{},
|
|
RWMutex: &sync.RWMutex{},
|
|
Notifier: nil,
|
|
}
|
|
for _, v := range opt {
|
|
v(c)
|
|
}
|
|
return c
|
|
}
|
|
|
|
func (c *checkerHandler) setNotifier(w Notifier) {
|
|
c.Notifier = w
|
|
}
|
|
|
|
func (c *checkerHandler) getName() string {
|
|
return c.Name
|
|
}
|
|
|
|
func (c *checkerHandler) check(ctx context.Context) bool {
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
|
|
}
|
|
}()
|
|
|
|
var cancel func()
|
|
if c.timeout > 0 {
|
|
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,
|
|
}
|
|
|
|
return c.CheckerStatus != old
|
|
}
|
|
|
|
func (c *checkerHandler) run(ctx context.Context) {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
default:
|
|
}
|
|
if c.check(ctx) {
|
|
//notify
|
|
if c.Notifier != nil {
|
|
c.Notifier.notify(c.Name)
|
|
}
|
|
}
|
|
time.Sleep(c.intervalTime)
|
|
}
|
|
}
|
|
|
|
func (c *checkerHandler) getStatus() CheckerStatus {
|
|
c.RLock()
|
|
defer c.RUnlock()
|
|
return c.CheckerStatus
|
|
}
|
|
|
|
type CheckOption func(handler *checkerHandler)
|
|
|
|
func WithInterval(interval time.Duration) CheckOption {
|
|
return func(handler *checkerHandler) {
|
|
handler.intervalTime = interval
|
|
}
|
|
}
|
|
|
|
func WithTimeout(timeout time.Duration) CheckOption {
|
|
return func(handler *checkerHandler) {
|
|
handler.timeout = timeout
|
|
}
|
|
}
|
|
|