Files
nezha_domains/cmd/dashboard/rpc/service_dispatch.go
T

89 lines
2.4 KiB
Go

package rpc
import (
"errors"
"log"
"github.com/nezhahq/nezha/model"
"github.com/nezhahq/nezha/proto"
"github.com/nezhahq/nezha/service/singleton"
)
func DispatchTask(serviceSentinelDispatchBus <-chan *model.Service) {
for task := range serviceSentinelDispatchBus {
if task == nil {
continue
}
if err := model.ValidateServiceMonitorType(uint64(task.Type)); err != nil {
// Defense in depth for stale database rows and future internal callers:
// Service.Type shares its integer namespace with command/config tasks.
log.Printf("NEZHA>> DispatchTask rejected service %d: %v", task.ID, err)
continue
}
probe := task.PB()
if probe == nil {
log.Printf("NEZHA>> DispatchTask rejected service %d: invalid probe", task.ID)
continue
}
switch task.Cover {
case model.ServiceCoverIgnoreAll:
for id, enabled := range task.SkipServers {
if !enabled {
continue
}
server, _ := singleton.ServerShared.Get(id)
if server == nil {
continue
}
if !canSendTaskToServer(task, server) {
continue
}
if err := server.SendTask(probe); err != nil && !errors.Is(err, model.ErrTaskStreamOffline) {
log.Printf("NEZHA>> DispatchTask send error (server=%d): %v", id, err)
}
}
case model.ServiceCoverAll:
for id, server := range singleton.ServerShared.GetList() {
if server == nil || task.SkipServers[id] {
continue
}
if !canSendTaskToServer(task, server) {
continue
}
if err := server.SendTask(probe); err != nil && !errors.Is(err, model.ErrTaskStreamOffline) {
log.Printf("NEZHA>> DispatchTask send error (server=%d): %v", id, err)
}
}
}
}
}
func DispatchKeepalive() {
singleton.CronShared.AddFunc("@every 20s", func() {
list := singleton.ServerShared.GetSortedList()
for _, s := range list {
if s == nil {
continue
}
if err := s.SendTask(&proto.Task{Type: model.TaskTypeKeepalive}); err != nil && !errors.Is(err, model.ErrTaskStreamOffline) {
log.Printf("NEZHA>> Keepalive send error (server=%d): %v", s.ID, err)
}
}
})
}
func canSendTaskToServer(task *model.Service, server *model.Server) bool {
var role model.Role
singleton.UserLock.RLock()
if u, ok := singleton.UserInfoMap[task.UserID]; !ok {
role = model.RoleMember
} else {
role = u.Role
}
singleton.UserLock.RUnlock()
return task.UserID == server.GetUserID() || role.IsAdmin()
}