diff --git a/cmd/init.go b/cmd/init.go index 61b086c..7427f20 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -6,9 +6,9 @@ import ( ) func Init(cmd *cobra.Command, args []string) error { + bootstrap.InitSysNotify() bootstrap.InitConfig() bootstrap.InitLog() - bootstrap.InitSysNotify() return nil } diff --git a/cmd/server.go b/cmd/server.go index 1a978cb..dedef2b 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -109,7 +109,7 @@ func Server(cmd *cobra.Command, args []string) { } else { log.Infof("website run on http://%s:%d", tcpServerAddr.IP, tcpServerAddr.Port) } - bootstrap.WaitCbk() + bootstrap.SysNotify.WaitCbk() } func init() { diff --git a/internal/bootstrap/sysNotify.go b/internal/bootstrap/sysNotify.go index 75ac7d4..d3aa87e 100644 --- a/internal/bootstrap/sysNotify.go +++ b/internal/bootstrap/sysNotify.go @@ -1,81 +1,11 @@ package bootstrap -import ( - "errors" - "os" - "sync" - - log "github.com/sirupsen/logrus" - - "github.com/zijiren233/gencontainer/pqueue" - "github.com/zijiren233/gencontainer/rwmap" -) +import sysnotify "github.com/synctv-org/synctv/utils/sysNotify" var ( - c chan os.Signal - once sync.Once - TaskGroup rwmap.RWMap[NotifyType, *taskQueue] - WaitCbk func() + SysNotify *sysnotify.SysNotify ) -type NotifyType int - -const ( - NotifyTypeEXIT NotifyType = iota + 1 - NotifyTypeRELOAD -) - -type taskQueue struct { - notifyTaskLock sync.Mutex - notifyTaskQueue *pqueue.PQueue[*SysNotifyTask] -} - -type SysNotifyTask struct { - Task func() error - NotifyType NotifyType - Name string -} - -func NewSysNotifyTask(name string, NotifyType NotifyType, task func() error) *SysNotifyTask { - return &SysNotifyTask{ - Name: name, - NotifyType: NotifyType, - Task: task, - } -} - -func runTask(tq *taskQueue) { - tq.notifyTaskLock.Lock() - defer tq.notifyTaskLock.Unlock() - for tq.notifyTaskQueue.Len() > 0 { - _, task := tq.notifyTaskQueue.Pop() - func() { - defer func() { - if err := recover(); err != nil { - log.Errorf("task: %s panic has returned: %v", task.Name, err) - } - }() - log.Infof("task: %s running", task.Name) - if err := task.Task(); err != nil { - log.Errorf("task: %s an error occurred: %v", task.Name, err) - } - log.Infof("task: %s done", task.Name) - }() - } -} - -func RegisterSysNotifyTask(priority int, task *SysNotifyTask) error { - if task == nil || task.Task == nil { - return errors.New("task is nil") - } - if task.NotifyType == 0 { - panic("task notify type is 0") - } - tasks, _ := TaskGroup.LoadOrStore(task.NotifyType, &taskQueue{ - notifyTaskQueue: pqueue.NewMinPriorityQueue[*SysNotifyTask](), - }) - tasks.notifyTaskLock.Lock() - defer tasks.notifyTaskLock.Unlock() - tasks.notifyTaskQueue.Push(priority, task) - return nil +func InitSysNotify() { + SysNotify = sysnotify.New() } diff --git a/internal/bootstrap/sysNotifySignal.go b/internal/bootstrap/sysNotifySignal.go deleted file mode 100644 index 8e60817..0000000 --- a/internal/bootstrap/sysNotifySignal.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build !windows -// +build !windows - -package bootstrap - -import ( - "os" - "os/signal" - "syscall" - - log "github.com/sirupsen/logrus" -) - -func InitSysNotify() { - c = make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGHUP /*1*/, syscall.SIGINT /*2*/, syscall.SIGQUIT /*3*/, syscall.SIGTERM /*15*/, syscall.SIGUSR1 /*10*/, syscall.SIGUSR2 /*12*/) - WaitCbk = func() { - once.Do(waitCbk) - } -} - -func waitCbk() { - log.Info("wait sys notify") - for s := range c { - log.Infof("receive sys notify: %v", s) - switch s { - case syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM: - tq, ok := TaskGroup.Load(NotifyTypeEXIT) - if ok { - log.Info("task: NotifyTypeEXIT running...") - runTask(tq) - } - return - case syscall.SIGUSR1, syscall.SIGUSR2: - tq, ok := TaskGroup.Load(NotifyTypeRELOAD) - if ok { - log.Info("task: NotifyTypeRELOAD running...") - runTask(tq) - } - } - log.Info("task: all done") - } -} diff --git a/internal/bootstrap/sysNotifySignal_windows.go b/internal/bootstrap/sysNotifySignal_windows.go deleted file mode 100644 index 1c65749..0000000 --- a/internal/bootstrap/sysNotifySignal_windows.go +++ /dev/null @@ -1,34 +0,0 @@ -package bootstrap - -import ( - "os" - "os/signal" - "syscall" - - log "github.com/sirupsen/logrus" -) - -func InitSysNotify() { - c = make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGHUP /*1*/, syscall.SIGINT /*2*/, syscall.SIGQUIT /*3*/, syscall.SIGTERM /*15*/) - WaitCbk = func() { - once.Do(waitCbk) - } -} - -func waitCbk() { - log.Info("wait sys notify") - for s := range c { - log.Infof("receive sys notify: %v", s) - switch s { - case syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM: - tq, ok := TaskGroup.Load(NotifyTypeEXIT) - if ok { - log.Info("task: NotifyTypeEXIT running...") - runTask(tq) - } - return - } - log.Info("task: all done") - } -} diff --git a/utils/sysNotify/signal.go b/utils/sysNotify/signal.go new file mode 100644 index 0000000..53e4856 --- /dev/null +++ b/utils/sysNotify/signal.go @@ -0,0 +1,29 @@ +//go:build !windows +// +build !windows + +package sysnotify + +import ( + "os" + "os/signal" + "syscall" +) + +func New() *SysNotify { + s := &SysNotify{ + c: make(chan os.Signal, 1), + } + signal.Notify(s.c, syscall.SIGHUP /*1*/, syscall.SIGINT /*2*/, syscall.SIGQUIT /*3*/, syscall.SIGTERM /*15*/, syscall.SIGUSR1 /*10*/, syscall.SIGUSR2 /*12*/) + return s +} + +func parseSysNotifyType(s os.Signal) NotifyType { + switch s { + case syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM: + return NotifyTypeEXIT + case syscall.SIGUSR1, syscall.SIGUSR2: + return NotifyTypeRELOAD + default: + return 0 + } +} diff --git a/utils/sysNotify/signal_windows.go b/utils/sysNotify/signal_windows.go new file mode 100644 index 0000000..52325f8 --- /dev/null +++ b/utils/sysNotify/signal_windows.go @@ -0,0 +1,24 @@ +package sysnotify + +import ( + "os" + "os/signal" + "syscall" +) + +func New() *SysNotify { + s := &SysNotify{ + c: make(chan os.Signal, 1), + } + signal.Notify(s.c, syscall.SIGHUP /*1*/, syscall.SIGINT /*2*/, syscall.SIGQUIT /*3*/, syscall.SIGTERM /*15*/) + return s +} + +func parseSysNotifyType(s os.Signal) NotifyType { + switch s { + case syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM: + return NotifyTypeEXIT + default: + return 0 + } +} diff --git a/utils/sysNotify/sysNotify.go b/utils/sysNotify/sysNotify.go new file mode 100644 index 0000000..aabe2c6 --- /dev/null +++ b/utils/sysNotify/sysNotify.go @@ -0,0 +1,107 @@ +package sysnotify + +import ( + "errors" + "os" + "sync" + + log "github.com/sirupsen/logrus" + + "github.com/zijiren233/gencontainer/pqueue" + "github.com/zijiren233/gencontainer/rwmap" +) + +type SysNotify struct { + c chan os.Signal + once sync.Once + taskGroup rwmap.RWMap[NotifyType, *taskQueue] +} + +type NotifyType int + +const ( + NotifyTypeEXIT NotifyType = iota + 1 + NotifyTypeRELOAD +) + +type taskQueue struct { + notifyTaskLock sync.Mutex + notifyTaskQueue *pqueue.PQueue[*sysNotifyTask] +} + +type sysNotifyTask struct { + Task func() error + NotifyType NotifyType + Name string +} + +func NewSysNotifyTask(name string, NotifyType NotifyType, task func() error) *sysNotifyTask { + return &sysNotifyTask{ + Name: name, + NotifyType: NotifyType, + Task: task, + } +} + +func runTask(tq *taskQueue) { + tq.notifyTaskLock.Lock() + defer tq.notifyTaskLock.Unlock() + for tq.notifyTaskQueue.Len() > 0 { + _, task := tq.notifyTaskQueue.Pop() + func() { + defer func() { + if err := recover(); err != nil { + log.Errorf("task: %s panic has returned: %v", task.Name, err) + } + }() + log.Infof("task: %s running", task.Name) + if err := task.Task(); err != nil { + log.Errorf("task: %s an error occurred: %v", task.Name, err) + } + log.Infof("task: %s done", task.Name) + }() + } +} + +func (sn *SysNotify) RegisterSysNotifyTask(priority int, task *sysNotifyTask) error { + if task == nil || task.Task == nil { + return errors.New("task is nil") + } + if task.NotifyType == 0 { + panic("task notify type is 0") + } + tasks, _ := sn.taskGroup.LoadOrStore(task.NotifyType, &taskQueue{ + notifyTaskQueue: pqueue.NewMinPriorityQueue[*sysNotifyTask](), + }) + tasks.notifyTaskLock.Lock() + defer tasks.notifyTaskLock.Unlock() + tasks.notifyTaskQueue.Push(priority, task) + return nil +} + +func (sn *SysNotify) waitCbk() { + log.Info("wait sys notify") + for s := range sn.c { + log.Infof("receive sys notify: %v", s) + switch parseSysNotifyType(s) { + case NotifyTypeEXIT: + tq, ok := sn.taskGroup.Load(NotifyTypeEXIT) + if ok { + log.Info("task: NotifyTypeEXIT running...") + runTask(tq) + } + return + case NotifyTypeRELOAD: + tq, ok := sn.taskGroup.Load(NotifyTypeRELOAD) + if ok { + log.Info("task: NotifyTypeRELOAD running...") + runTask(tq) + } + } + log.Info("task: all done") + } +} + +func (sn *SysNotify) WaitCbk() { + sn.once.Do(sn.waitCbk) +}