refactor: simplify server & service manipulation (#993)

* refactor: simplify server & service manipulation

* update

* fix

* update for nat, ddns & notification

* chore

* update cron

* update dependencies

* use of function iterators

* update default dns servers
This commit is contained in:
UUBulb
2025-02-21 23:08:12 +08:00
committed by GitHub
parent 21eefde995
commit 91bef2882a
32 changed files with 987 additions and 1083 deletions

View File

@@ -1,6 +1,7 @@
package controller
import (
"maps"
"strconv"
"time"
@@ -168,16 +169,9 @@ func batchDeleteAlertRule(c *gin.Context) (any, error) {
func validateRule(c *gin.Context, r *model.AlertRule) error {
if len(r.Rules) > 0 {
for _, rule := range r.Rules {
singleton.ServerLock.RLock()
for s := range rule.Ignore {
if server, ok := singleton.ServerList[s]; ok {
if !server.HasPermission(c) {
singleton.ServerLock.RUnlock()
return singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.ServerShared.CheckPermission(c, maps.Keys(rule.Ignore)) {
return singleton.Localizer.ErrorT("permission denied")
}
singleton.ServerLock.RUnlock()
if !rule.IsTransferDurationRule() {
if rule.Duration < 3 {

View File

@@ -1,6 +1,7 @@
package controller
import (
"slices"
"strconv"
"github.com/gin-gonic/gin"
@@ -21,11 +22,10 @@ import (
// @Success 200 {object} model.CommonResponse[[]model.Cron]
// @Router /cron [get]
func listCron(c *gin.Context) ([]*model.Cron, error) {
singleton.CronLock.RLock()
defer singleton.CronLock.RUnlock()
slist := singleton.CronShared.GetSortedList()
var cr []*model.Cron
if err := copier.Copy(&cr, &singleton.CronList); err != nil {
if err := copier.Copy(&cr, &slist); err != nil {
return nil, err
}
return cr, nil
@@ -50,16 +50,9 @@ func createCron(c *gin.Context) (uint64, error) {
return 0, err
}
singleton.ServerLock.RLock()
for _, sid := range cf.Servers {
if server, ok := singleton.ServerList[sid]; ok {
if !server.HasPermission(c) {
singleton.ServerLock.RUnlock()
return 0, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.ServerShared.CheckPermission(c, slices.Values(cf.Servers)) {
return 0, singleton.Localizer.ErrorT("permission denied")
}
singleton.ServerLock.RUnlock()
cr.UserID = getUid(c)
cr.TaskType = cf.TaskType
@@ -78,7 +71,7 @@ func createCron(c *gin.Context) (uint64, error) {
// 对于计划任务类型需要更新CronJob
var err error
if cf.TaskType == model.CronTypeCronTask {
if cr.CronJobID, err = singleton.Cron.AddFunc(cr.Scheduler, singleton.CronTrigger(&cr)); err != nil {
if cr.CronJobID, err = singleton.CronShared.AddFunc(cr.Scheduler, singleton.CronTrigger(&cr)); err != nil {
return 0, err
}
}
@@ -87,8 +80,7 @@ func createCron(c *gin.Context) (uint64, error) {
return 0, newGormError("%v", err)
}
singleton.OnRefreshOrAddCron(&cr)
singleton.UpdateCronList()
singleton.CronShared.Update(&cr)
return cr.ID, nil
}
@@ -116,16 +108,9 @@ func updateCron(c *gin.Context) (any, error) {
return 0, err
}
singleton.ServerLock.RLock()
for _, sid := range cf.Servers {
if server, ok := singleton.ServerList[sid]; ok {
if !server.HasPermission(c) {
singleton.ServerLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.ServerShared.CheckPermission(c, slices.Values(cf.Servers)) {
return 0, singleton.Localizer.ErrorT("permission denied")
}
singleton.ServerLock.RUnlock()
var cr model.Cron
if err := singleton.DB.First(&cr, id).Error; err != nil {
@@ -151,7 +136,7 @@ func updateCron(c *gin.Context) (any, error) {
// 对于计划任务类型需要更新CronJob
if cf.TaskType == model.CronTypeCronTask {
if cr.CronJobID, err = singleton.Cron.AddFunc(cr.Scheduler, singleton.CronTrigger(&cr)); err != nil {
if cr.CronJobID, err = singleton.CronShared.AddFunc(cr.Scheduler, singleton.CronTrigger(&cr)); err != nil {
return nil, err
}
}
@@ -160,8 +145,7 @@ func updateCron(c *gin.Context) (any, error) {
return nil, newGormError("%v", err)
}
singleton.OnRefreshOrAddCron(&cr)
singleton.UpdateCronList()
singleton.CronShared.Update(&cr)
return nil, nil
}
@@ -183,13 +167,10 @@ func manualTriggerCron(c *gin.Context) (any, error) {
return nil, err
}
singleton.CronLock.RLock()
cr, ok := singleton.Crons[id]
cr, ok := singleton.CronShared.Get(id)
if !ok {
singleton.CronLock.RUnlock()
return nil, singleton.Localizer.ErrorT("task id %d does not exist", id)
}
singleton.CronLock.RUnlock()
if !cr.HasPermission(c) {
return nil, singleton.Localizer.ErrorT("permission denied")
@@ -216,22 +197,14 @@ func batchDeleteCron(c *gin.Context) (any, error) {
return nil, err
}
singleton.CronLock.RLock()
for _, crID := range cr {
if crn, ok := singleton.Crons[crID]; ok {
if !crn.HasPermission(c) {
singleton.CronLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.CronShared.CheckPermission(c, slices.Values(cr)) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.CronLock.RUnlock()
if err := singleton.DB.Unscoped().Delete(&model.Cron{}, "id in (?)", cr).Error; err != nil {
return nil, newGormError("%v", err)
}
singleton.OnDeleteCron(cr)
singleton.UpdateCronList()
singleton.CronShared.Delete(cr)
return nil, nil
}

View File

@@ -1,6 +1,7 @@
package controller
import (
"slices"
"strconv"
"github.com/gin-gonic/gin"
@@ -24,10 +25,8 @@ import (
func listDDNS(c *gin.Context) ([]*model.DDNSProfile, error) {
var ddnsProfiles []*model.DDNSProfile
singleton.DDNSListLock.RLock()
defer singleton.DDNSListLock.RUnlock()
if err := copier.Copy(&ddnsProfiles, &singleton.DDNSList); err != nil {
list := singleton.DDNSShared.GetSortedList()
if err := copier.Copy(&ddnsProfiles, &list); err != nil {
return nil, err
}
@@ -87,9 +86,7 @@ func createDDNS(c *gin.Context) (uint64, error) {
return 0, newGormError("%v", err)
}
singleton.OnDDNSUpdate(&p)
singleton.UpdateDDNSList()
singleton.DDNSShared.Update(&p)
return p.ID, nil
}
@@ -160,8 +157,7 @@ func updateDDNS(c *gin.Context) (any, error) {
return nil, newGormError("%v", err)
}
singleton.OnDDNSUpdate(&p)
singleton.UpdateDDNSList()
singleton.DDNSShared.Update(&p)
return nil, nil
}
@@ -184,24 +180,15 @@ func batchDeleteDDNS(c *gin.Context) (any, error) {
return nil, err
}
singleton.DDNSCacheLock.RLock()
for _, pid := range ddnsConfigs {
if p, ok := singleton.DDNSCache[pid]; ok {
if !p.HasPermission(c) {
singleton.DDNSCacheLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.DDNSShared.CheckPermission(c, slices.Values(ddnsConfigs)) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.DDNSCacheLock.RUnlock()
if err := singleton.DB.Unscoped().Delete(&model.DDNSProfile{}, "id in (?)", ddnsConfigs).Error; err != nil {
return nil, newGormError("%v", err)
}
singleton.OnDDNSDelete(ddnsConfigs)
singleton.UpdateDDNSList()
singleton.DDNSShared.Delete(ddnsConfigs)
return nil, nil
}

View File

@@ -32,9 +32,7 @@ func createFM(c *gin.Context) (*model.CreateFMResponse, error) {
return nil, err
}
singleton.ServerLock.RLock()
server := singleton.ServerList[id]
singleton.ServerLock.RUnlock()
server, _ := singleton.ServerShared.Get(id)
if server == nil || server.TaskStream == nil {
return nil, singleton.Localizer.ErrorT("server not found or not connected")
}

View File

@@ -1,12 +1,14 @@
package controller
import (
"slices"
"strconv"
"github.com/gin-gonic/gin"
"github.com/jinzhu/copier"
"github.com/nezhahq/nezha/model"
"github.com/nezhahq/nezha/pkg/utils"
"github.com/nezhahq/nezha/service/singleton"
)
@@ -23,10 +25,9 @@ import (
func listNAT(c *gin.Context) ([]*model.NAT, error) {
var n []*model.NAT
singleton.NATListLock.RLock()
defer singleton.NATListLock.RUnlock()
slist := singleton.NATShared.GetSortedList()
if err := copier.Copy(&n, &singleton.NATList); err != nil {
if err := copier.Copy(&n, &slist); err != nil {
return nil, err
}
@@ -52,14 +53,11 @@ func createNAT(c *gin.Context) (uint64, error) {
return 0, err
}
singleton.ServerLock.RLock()
if server, ok := singleton.ServerList[nf.ServerID]; ok {
if server, ok := singleton.ServerShared.Get(nf.ServerID); ok {
if !server.HasPermission(c) {
singleton.ServerLock.RUnlock()
return 0, singleton.Localizer.ErrorT("permission denied")
}
}
singleton.ServerLock.RUnlock()
uid := getUid(c)
@@ -74,8 +72,7 @@ func createNAT(c *gin.Context) (uint64, error) {
return 0, newGormError("%v", err)
}
singleton.OnNATUpdate(&n)
singleton.UpdateNATList()
singleton.NATShared.Update(&n)
return n.ID, nil
}
@@ -104,14 +101,11 @@ func updateNAT(c *gin.Context) (any, error) {
return nil, err
}
singleton.ServerLock.RLock()
if server, ok := singleton.ServerList[nf.ServerID]; ok {
if server, ok := singleton.ServerShared.Get(nf.ServerID); ok {
if !server.HasPermission(c) {
singleton.ServerLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
singleton.ServerLock.RUnlock()
var n model.NAT
if err = singleton.DB.First(&n, id).Error; err != nil {
@@ -132,8 +126,7 @@ func updateNAT(c *gin.Context) (any, error) {
return 0, newGormError("%v", err)
}
singleton.OnNATUpdate(&n)
singleton.UpdateNATList()
singleton.NATShared.Update(&n)
return nil, nil
}
@@ -154,22 +147,17 @@ func batchDeleteNAT(c *gin.Context) (any, error) {
return nil, err
}
singleton.NATCacheRwLock.RLock()
for _, id := range n {
if p, ok := singleton.NATCache[singleton.NATIDToDomain[id]]; ok {
if !p.HasPermission(c) {
singleton.NATCacheRwLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.NATShared.CheckPermission(c, utils.ConvertSeq(slices.Values(n),
func(id uint64) string {
return singleton.NATShared.GetDomain(id)
})) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.NATCacheRwLock.RUnlock()
if err := singleton.DB.Unscoped().Delete(&model.NAT{}, "id in (?)", n).Error; err != nil {
return nil, newGormError("%v", err)
}
singleton.OnNATDelete(n)
singleton.UpdateNATList()
singleton.NATShared.Delete(n)
return nil, nil
}

View File

@@ -1,13 +1,15 @@
package controller
import (
"slices"
"strconv"
"github.com/gin-gonic/gin"
"github.com/jinzhu/copier"
"gorm.io/gorm"
"github.com/nezhahq/nezha/model"
"github.com/nezhahq/nezha/service/singleton"
"gorm.io/gorm"
)
// List notification
@@ -21,11 +23,10 @@ import (
// @Success 200 {object} model.CommonResponse[[]model.Notification]
// @Router /notification [get]
func listNotification(c *gin.Context) ([]*model.Notification, error) {
singleton.NotificationSortedLock.RLock()
defer singleton.NotificationSortedLock.RUnlock()
slist := singleton.NotificationShared.GetSortedList()
var notifications []*model.Notification
if err := copier.Copy(&notifications, &singleton.NotificationListSorted); err != nil {
if err := copier.Copy(&notifications, &slist); err != nil {
return nil, err
}
return notifications, nil
@@ -75,8 +76,7 @@ func createNotification(c *gin.Context) (uint64, error) {
return 0, newGormError("%v", err)
}
singleton.OnRefreshOrAddNotification(&n)
singleton.UpdateNotificationList()
singleton.NotificationShared.Update(&n)
return n.ID, nil
}
@@ -137,8 +137,7 @@ func updateNotification(c *gin.Context) (any, error) {
return nil, newGormError("%v", err)
}
singleton.OnRefreshOrAddNotification(&n)
singleton.UpdateNotificationList()
singleton.NotificationShared.Update(&n)
return nil, nil
}
@@ -159,16 +158,9 @@ func batchDeleteNotification(c *gin.Context) (any, error) {
return nil, err
}
singleton.NotificationsLock.RLock()
for _, nid := range n {
if ns, ok := singleton.NotificationMap[nid]; ok {
if !ns.HasPermission(c) {
singleton.NotificationsLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.NotificationShared.CheckPermission(c, slices.Values(n)) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.NotificationsLock.RUnlock()
err := singleton.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Unscoped().Delete(&model.Notification{}, "id in (?)", n).Error; err != nil {
@@ -184,7 +176,6 @@ func batchDeleteNotification(c *gin.Context) (any, error) {
return nil, newGormError("%v", err)
}
singleton.OnDeleteNotification(n)
singleton.UpdateNotificationList()
singleton.NotificationShared.Delete(n)
return nil, nil
}

View File

@@ -68,16 +68,9 @@ func createNotificationGroup(c *gin.Context) (uint64, error) {
}
ngf.Notifications = slices.Compact(ngf.Notifications)
singleton.NotificationsLock.RLock()
for _, nid := range ngf.Notifications {
if n, ok := singleton.NotificationMap[nid]; ok {
if !n.HasPermission(c) {
singleton.NotificationsLock.RUnlock()
return 0, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.NotificationShared.CheckPermission(c, slices.Values(ngf.Notifications)) {
return 0, singleton.Localizer.ErrorT("permission denied")
}
singleton.NotificationsLock.RUnlock()
uid := getUid(c)
@@ -115,7 +108,7 @@ func createNotificationGroup(c *gin.Context) (uint64, error) {
return 0, newGormError("%v", err)
}
singleton.OnRefreshOrAddNotificationGroup(&ng, ngf.Notifications)
singleton.NotificationShared.UpdateGroup(&ng, ngf.Notifications)
return ng.ID, nil
}
@@ -144,16 +137,9 @@ func updateNotificationGroup(c *gin.Context) (any, error) {
return nil, err
}
singleton.NotificationsLock.RLock()
for _, nid := range ngf.Notifications {
if n, ok := singleton.NotificationMap[nid]; ok {
if !n.HasPermission(c) {
singleton.NotificationsLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.NotificationShared.CheckPermission(c, slices.Values(ngf.Notifications)) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.NotificationsLock.RUnlock()
var ngDB model.NotificationGroup
if err := singleton.DB.First(&ngDB, id).Error; err != nil {
@@ -202,7 +188,7 @@ func updateNotificationGroup(c *gin.Context) (any, error) {
return nil, newGormError("%v", err)
}
singleton.OnRefreshOrAddNotificationGroup(&ngDB, ngf.Notifications)
singleton.NotificationShared.UpdateGroup(&ngDB, ngf.Notifications)
return nil, nil
}
@@ -248,6 +234,6 @@ func batchDeleteNotificationGroup(c *gin.Context) (any, error) {
return nil, newGormError("%v", err)
}
singleton.OnDeleteNotificationGroup(ngn)
singleton.NotificationShared.DeleteGroup(ngn)
return nil, nil
}

View File

@@ -1,6 +1,7 @@
package controller
import (
"slices"
"strconv"
"sync"
"time"
@@ -26,11 +27,10 @@ import (
// @Success 200 {object} model.CommonResponse[[]model.Server]
// @Router /server [get]
func listServer(c *gin.Context) ([]*model.Server, error) {
singleton.SortedServerLock.RLock()
defer singleton.SortedServerLock.RUnlock()
slist := singleton.ServerShared.GetSortedList()
var ssl []*model.Server
if err := copier.Copy(&ssl, &singleton.SortedServerList); err != nil {
if err := copier.Copy(&ssl, &slist); err != nil {
return nil, err
}
return ssl, nil
@@ -59,16 +59,9 @@ func updateServer(c *gin.Context) (any, error) {
return nil, err
}
singleton.DDNSCacheLock.RLock()
for _, pid := range sf.DDNSProfiles {
if p, ok := singleton.DDNSCache[pid]; ok {
if !p.HasPermission(c) {
singleton.DDNSCacheLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.DDNSShared.CheckPermission(c, slices.Values(sf.DDNSProfiles)) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.DDNSCacheLock.RUnlock()
var s model.Server
if err := singleton.DB.First(&s, id).Error; err != nil {
@@ -104,11 +97,9 @@ func updateServer(c *gin.Context) (any, error) {
return nil, newGormError("%v", err)
}
singleton.ServerLock.Lock()
s.CopyFromRunningServer(singleton.ServerList[s.ID])
singleton.ServerList[s.ID] = &s
singleton.ServerLock.Unlock()
singleton.ReSortServer()
rs, _ := singleton.ServerShared.Get(s.ID)
s.CopyFromRunningServer(rs)
singleton.ServerShared.Update(&s, "")
return nil, nil
}
@@ -130,16 +121,9 @@ func batchDeleteServer(c *gin.Context) (any, error) {
return nil, err
}
singleton.ServerLock.RLock()
for _, sid := range servers {
if s, ok := singleton.ServerList[sid]; ok {
if !s.HasPermission(c) {
singleton.ServerLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.ServerShared.CheckPermission(c, slices.Values(servers)) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.ServerLock.RUnlock()
err := singleton.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Unscoped().Delete(&model.Server{}, "id in (?)", servers).Error; err != nil {
@@ -168,9 +152,7 @@ func batchDeleteServer(c *gin.Context) (any, error) {
singleton.DB.Unscoped().Delete(&model.Transfer{}, "server_id in (?)", servers)
singleton.AlertsLock.Unlock()
singleton.OnServerDelete(servers)
singleton.ReSortServer()
singleton.ServerShared.Delete(servers)
return nil, nil
}
@@ -194,9 +176,7 @@ func forceUpdateServer(c *gin.Context) (*model.ServerTaskResponse, error) {
forceUpdateResp := new(model.ServerTaskResponse)
for _, sid := range forceUpdateServers {
singleton.ServerLock.RLock()
server := singleton.ServerList[sid]
singleton.ServerLock.RUnlock()
server, _ := singleton.ServerShared.Get(sid)
if server != nil && server.TaskStream != nil {
if !server.HasPermission(c) {
return nil, singleton.Localizer.ErrorT("permission denied")
@@ -232,13 +212,10 @@ func getServerConfig(c *gin.Context) (string, error) {
return "", err
}
singleton.ServerLock.RLock()
s, ok := singleton.ServerList[id]
s, ok := singleton.ServerShared.Get(id)
if !ok || s.TaskStream == nil {
singleton.ServerLock.RUnlock()
return "", nil
}
singleton.ServerLock.RUnlock()
if !s.HasPermission(c) {
return "", singleton.Localizer.ErrorT("permission denied")
@@ -285,12 +262,11 @@ func setServerConfig(c *gin.Context) (*model.ServerTaskResponse, error) {
}
var resp model.ServerTaskResponse
singleton.ServerLock.RLock()
slist := singleton.ServerShared.GetList()
servers := make([]*model.Server, 0, len(configForm.Servers))
for _, sid := range configForm.Servers {
if s, ok := singleton.ServerList[sid]; ok {
if s, ok := slist[sid]; ok {
if !s.HasPermission(c) {
singleton.ServerLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
if s.TaskStream == nil {
@@ -300,7 +276,6 @@ func setServerConfig(c *gin.Context) (*model.ServerTaskResponse, error) {
servers = append(servers, s)
}
}
singleton.ServerLock.RUnlock()
var wg sync.WaitGroup
var respMu sync.Mutex

View File

@@ -67,16 +67,9 @@ func createServerGroup(c *gin.Context) (uint64, error) {
}
sgf.Servers = slices.Compact(sgf.Servers)
singleton.ServerLock.RLock()
for _, sid := range sgf.Servers {
if server, ok := singleton.ServerList[sid]; ok {
if !server.HasPermission(c) {
singleton.ServerLock.RUnlock()
return 0, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.ServerShared.CheckPermission(c, slices.Values(sgf.Servers)) {
return 0, singleton.Localizer.ErrorT("permission denied")
}
singleton.ServerLock.RUnlock()
uid := getUid(c)
@@ -142,16 +135,9 @@ func updateServerGroup(c *gin.Context) (any, error) {
}
sg.Servers = slices.Compact(sg.Servers)
singleton.ServerLock.RLock()
for _, sid := range sg.Servers {
if server, ok := singleton.ServerList[sid]; ok {
if !server.HasPermission(c) {
singleton.ServerLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.ServerShared.CheckPermission(c, slices.Values(sg.Servers)) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.ServerLock.RUnlock()
var sgDB model.ServerGroup
if err := singleton.DB.First(&sgDB, id).Error; err != nil {

View File

@@ -1,6 +1,8 @@
package controller
import (
"maps"
"slices"
"strconv"
"strings"
"time"
@@ -55,11 +57,9 @@ func showService(c *gin.Context) (*model.ServiceResponse, error) {
// @Success 200 {object} model.CommonResponse[[]model.Service]
// @Router /service [get]
func listService(c *gin.Context) ([]*model.Service, error) {
singleton.ServiceSentinelShared.ServicesLock.RLock()
defer singleton.ServiceSentinelShared.ServicesLock.RUnlock()
var ss []*model.Service
if err := copier.Copy(&ss, singleton.ServiceSentinelShared.ServiceList); err != nil {
ssl := singleton.ServiceSentinelShared.GetSortedList()
if err := copier.Copy(&ss, &ssl); err != nil {
return nil, err
}
@@ -83,9 +83,8 @@ func listServiceHistory(c *gin.Context) ([]*model.ServiceInfos, error) {
return nil, err
}
singleton.ServerLock.RLock()
server, ok := singleton.ServerList[id]
singleton.ServerLock.RUnlock()
m := singleton.ServerShared.GetList()
server, ok := m[id]
if !ok || server == nil {
return nil, singleton.Localizer.ErrorT("server not found")
}
@@ -104,21 +103,17 @@ func listServiceHistory(c *gin.Context) ([]*model.ServiceInfos, error) {
return nil, err
}
singleton.ServiceSentinelShared.ServicesLock.RLock()
defer singleton.ServiceSentinelShared.ServicesLock.RUnlock()
singleton.ServerLock.RLock()
defer singleton.ServerLock.RUnlock()
var sortedServiceIDs []uint64
resultMap := make(map[uint64]*model.ServiceInfos)
for _, history := range serviceHistories {
infos, ok := resultMap[history.ServiceID]
service, _ := singleton.ServiceSentinelShared.Get(history.ServiceID)
if !ok {
infos = &model.ServiceInfos{
ServiceID: history.ServiceID,
ServerID: history.ServerID,
ServiceName: singleton.ServiceSentinelShared.Services[history.ServiceID].Name,
ServerName: singleton.ServerList[history.ServerID].Name,
ServiceName: service.Name,
ServerName: m[history.ServerID].Name,
}
resultMap[history.ServiceID] = infos
sortedServiceIDs = append(sortedServiceIDs, history.ServiceID)
@@ -158,9 +153,7 @@ func listServerWithServices(c *gin.Context) ([]uint64, error) {
var ret []uint64
for _, id := range serverIdsWithService {
singleton.ServerLock.RLock()
server, ok := singleton.ServerList[id]
singleton.ServerLock.RUnlock()
server, ok := singleton.ServerShared.Get(id)
if !ok || server == nil {
return nil, singleton.Localizer.ErrorT("server not found")
}
@@ -232,7 +225,7 @@ func createService(c *gin.Context) (uint64, error) {
return 0, err
}
if err := singleton.ServiceSentinelShared.OnServiceUpdate(m); err != nil {
if err := singleton.ServiceSentinelShared.Update(&m); err != nil {
return 0, err
}
@@ -309,7 +302,7 @@ func updateService(c *gin.Context) (any, error) {
return nil, err
}
if err := singleton.ServiceSentinelShared.OnServiceUpdate(m); err != nil {
if err := singleton.ServiceSentinelShared.Update(&m); err != nil {
return nil, err
}
@@ -334,16 +327,9 @@ func batchDeleteService(c *gin.Context) (any, error) {
return nil, err
}
singleton.ServiceSentinelShared.ServicesLock.RLock()
for _, id := range ids {
if ss, ok := singleton.ServiceSentinelShared.Services[id]; ok {
if !ss.HasPermission(c) {
singleton.ServiceSentinelShared.ServicesLock.RUnlock()
return nil, singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.ServiceSentinelShared.CheckPermission(c, slices.Values(ids)) {
return nil, singleton.Localizer.ErrorT("permission denied")
}
singleton.ServiceSentinelShared.ServicesLock.RUnlock()
err := singleton.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Unscoped().Delete(&model.Service{}, "id in (?)", ids).Error; err != nil {
@@ -354,21 +340,14 @@ func batchDeleteService(c *gin.Context) (any, error) {
if err != nil {
return nil, err
}
singleton.ServiceSentinelShared.OnServiceDelete(ids)
singleton.ServiceSentinelShared.Delete(ids)
singleton.ServiceSentinelShared.UpdateServiceList()
return nil, nil
}
func validateServers(c *gin.Context, ss *model.Service) error {
singleton.ServerLock.RLock()
defer singleton.ServerLock.RUnlock()
for s := range ss.SkipServers {
if server, ok := singleton.ServerList[s]; ok {
if !server.HasPermission(c) {
return singleton.Localizer.ErrorT("permission denied")
}
}
if !singleton.ServerShared.CheckPermission(c, maps.Keys(ss.SkipServers)) {
return singleton.Localizer.ErrorT("permission denied")
}
return nil

View File

@@ -30,9 +30,7 @@ func createTerminal(c *gin.Context) (*model.CreateTerminalResponse, error) {
return nil, err
}
singleton.ServerLock.RLock()
server := singleton.ServerList[createTerminalReq.ServerID]
singleton.ServerLock.RUnlock()
server, _ := singleton.ServerShared.Get(createTerminalReq.ServerID)
if server == nil || server.TaskStream == nil {
return nil, singleton.Localizer.ErrorT("server not found or not connected")
}

View File

@@ -158,14 +158,11 @@ var requestGroup singleflight.Group
func getServerStat(withPublicNote, authorized bool) ([]byte, error) {
v, err, _ := requestGroup.Do(fmt.Sprintf("serverStats::%t", authorized), func() (interface{}, error) {
singleton.SortedServerLock.RLock()
defer singleton.SortedServerLock.RUnlock()
var serverList []*model.Server
if authorized {
serverList = singleton.SortedServerList
serverList = singleton.ServerShared.GetSortedList()
} else {
serverList = singleton.SortedServerListForGuest
serverList = singleton.ServerShared.GetSortedListForGuest()
}
servers := make([]model.StreamServer, 0, len(serverList))

View File

@@ -1,26 +0,0 @@
package controller
import (
"sync/atomic"
"testing"
)
func TestWs(t *testing.T) {
onlineUsers := new(atomic.Uint64)
onlineUsers.Add(1)
if onlineUsers.Load() != 1 {
t.Error("onlineUsers.Add(1) failed")
}
onlineUsers.Add(1)
if onlineUsers.Load() != 2 {
t.Error("onlineUsers.Add(1) failed")
}
onlineUsers.Add(^uint64(0))
if onlineUsers.Load() != 1 {
t.Error("onlineUsers.Add(^uint64(0)) failed")
}
onlineUsers.Add(^uint64(0))
if onlineUsers.Load() != 0 {
t.Error("onlineUsers.Add(^uint64(0)) failed")
}
}