123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- package hook
- import (
- "fmt"
- "os"
- "os/signal"
- "reflect"
- "sync"
- "syscall"
- "time"
- )
- type ShutdownHook struct {
- hooks map[string]func(os.Signal)
- hooksMain func(os.Signal)
- mutex *sync.Mutex
- }
- var defaultHook = &ShutdownHook{ mutex: &sync.Mutex{},hooks: map[string]func(os.Signal){}}
- func Listen(signals ...os.Signal) {
- defaultHook.Listen(signals...)
- }
- func RegistryHook(name string, fn func(string)) {
- defaultHook.RegistryHook(name, fn)
- }
- func RegistryMainHook(fn func()) {
- defaultHook.RegistryMainHook(fn)
- }
- func (s *ShutdownHook) RegistryMainHook(fn func()) {
- s.RegistryMainHookWithParam(func(os.Signal) {
- fmt.Printf("[####] main shutdown process start...\n")
- fn()
- fmt.Printf("[####] main shutdown process end...\n")
- })
- }
- func (s *ShutdownHook) RegistryHook(name string, fn func(string)) {
- s.RegistryHookWithParam(name, func(os.Signal) {
- fmt.Printf("[####] %v shutdown process start...\n", name)
- fn(name)
- fmt.Printf("[####] %v shutdown process end...\n", name)
- })
- }
- func (s *ShutdownHook) RegistryHookWithParam(name string, fn func(os.Signal)) {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- s.hooks[name] = fn
- }
- func (s *ShutdownHook) RegistryMainHookWithParam( fn func(os.Signal)) {
- s.hooksMain = fn
- }
- func (s *ShutdownHook) Hooks() map[string]func(os.Signal) {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- fns := map[string]func(os.Signal){}
- for k, v := range s.hooks {
- fns[k] = v
- }
- return fns
- }
- func (s *ShutdownHook) Listen(signals ...os.Signal) {
- ch := make(chan os.Signal, 1)
- var (
- sig os.Signal
- timeGap int64
- )
- for {
- signal.Notify(ch, signals...)
- sig = <-ch
- target := reflect.ValueOf(sig)
- fmt.Println("[######] Enter End Signal... [", target.String(),"]","[", sig.String(),"]")
- if sig == syscall.SIGINT {
- timeNow := time.Now().UnixNano()
- if timeNow < timeGap+(1000*int64(time.Millisecond)) {
- break
- }
- timeGap = time.Now().UnixNano()
- } else if sig == syscall.SIGTERM || sig == syscall.SIGKILL || sig == syscall.SIGQUIT { // Delete syscall.SIGHUP
- break
- }
- }
- fmt.Println("[######] shutdown process start... ", sig.String())
- // SUB HOOK PROCESS
- var wg sync.WaitGroup
- for _, fn := range s.Hooks() {
- wg.Add(1)
- go func(sig os.Signal, fn func(os.Signal)) {
- defer wg.Done()
- fn(sig)
- }(sig, fn)
- }
- wg.Wait()
- // MAIN HOOK PROCESS
- if s.hooksMain != nil {
- wg.Add(1)
- go func(sig os.Signal, fn func(os.Signal)) {
- defer wg.Done()
- fn(sig)
- }(sig, s.hooksMain)
- }
- wg.Wait()
- fmt.Println("[######] shutdown process complete...")
- }
|