improve: server list lock
Some checks are pending
CodeQL / Analyze (go) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Contributors / contributors (push) Waiting to run
Sync / sync-to-jihulab (push) Waiting to run
Run Tests / tests (macos) (push) Waiting to run
Run Tests / tests (ubuntu) (push) Waiting to run
Run Tests / tests (windows) (push) Waiting to run

This commit is contained in:
naiba 2025-01-04 01:10:16 +08:00
parent efdae906c2
commit 81a08a38da
2 changed files with 25 additions and 21 deletions

View File

@ -85,7 +85,8 @@ func listServiceHistory(c *gin.Context) ([]*model.ServiceInfos, error) {
singleton.ServerLock.RLock() singleton.ServerLock.RLock()
server, ok := singleton.ServerList[id] server, ok := singleton.ServerList[id]
if !ok { singleton.ServerLock.RUnlock()
if !ok || server == nil {
return nil, singleton.Localizer.ErrorT("server not found") return nil, singleton.Localizer.ErrorT("server not found")
} }
@ -95,7 +96,6 @@ func listServiceHistory(c *gin.Context) ([]*model.ServiceInfos, error) {
if server.HideForGuest && !authorized { if server.HideForGuest && !authorized {
return nil, singleton.Localizer.ErrorT("unauthorized") return nil, singleton.Localizer.ErrorT("unauthorized")
} }
singleton.ServerLock.RUnlock()
var serviceHistories []*model.ServiceHistory var serviceHistories []*model.ServiceHistory
if err := singleton.DB.Model(&model.ServiceHistory{}).Select("service_id, created_at, server_id, avg_delay"). if err := singleton.DB.Model(&model.ServiceHistory{}).Select("service_id, created_at, server_id, avg_delay").

View File

@ -103,20 +103,20 @@ func (s *NezhaHandler) ReportSystemState(stream pb.NezhaService_ReportSystemStat
state := model.PB2State(state) state := model.PB2State(state)
singleton.ServerLock.RLock() singleton.ServerLock.RLock()
server, ok := singleton.ServerList[clientID]
singleton.ServerLock.RUnlock()
if singleton.ServerList[clientID] == nil { if !ok || server == nil {
singleton.ServerLock.RUnlock()
return nil return nil
} }
singleton.ServerList[clientID].LastActive = time.Now() server.LastActive = time.Now()
singleton.ServerList[clientID].State = &state server.State = &state
// 应对 dashboard 重启的情况,如果从未记录过,先打点,等到小时时间点时入库 // 应对 dashboard 重启的情况,如果从未记录过,先打点,等到小时时间点时入库
if singleton.ServerList[clientID].PrevTransferInSnapshot == 0 || singleton.ServerList[clientID].PrevTransferOutSnapshot == 0 { if server.PrevTransferInSnapshot == 0 || server.PrevTransferOutSnapshot == 0 {
singleton.ServerList[clientID].PrevTransferInSnapshot = int64(state.NetInTransfer) server.PrevTransferInSnapshot = int64(state.NetInTransfer)
singleton.ServerList[clientID].PrevTransferOutSnapshot = int64(state.NetOutTransfer) server.PrevTransferOutSnapshot = int64(state.NetOutTransfer)
} }
singleton.ServerLock.RUnlock()
stream.Send(&pb.Receipt{Proced: true}) stream.Send(&pb.Receipt{Proced: true})
} }
@ -129,6 +129,7 @@ func (s *NezhaHandler) onReportSystemInfo(c context.Context, r *pb.Host) error {
return err return err
} }
host := model.PB2Host(r) host := model.PB2Host(r)
singleton.ServerLock.RLock() singleton.ServerLock.RLock()
defer singleton.ServerLock.RUnlock() defer singleton.ServerLock.RUnlock()
@ -214,12 +215,18 @@ func (s *NezhaHandler) ReportGeoIP(c context.Context, r *pb.GeoIP) (*pb.GeoIP, e
joinedIP := geoip.IP.Join() joinedIP := geoip.IP.Join()
singleton.ServerLock.RLock() singleton.ServerLock.RLock()
server, ok := singleton.ServerList[clientID]
singleton.ServerLock.RUnlock()
if !ok || server == nil {
return nil, fmt.Errorf("server not found")
}
// 检查并更新DDNS // 检查并更新DDNS
if singleton.ServerList[clientID].EnableDDNS && joinedIP != "" && if server.EnableDDNS && joinedIP != "" &&
(singleton.ServerList[clientID].GeoIP == nil || singleton.ServerList[clientID].GeoIP.IP != geoip.IP) { (server.GeoIP == nil || server.GeoIP.IP != geoip.IP) {
ipv4 := geoip.IP.IPv4Addr ipv4 := geoip.IP.IPv4Addr
ipv6 := geoip.IP.IPv6Addr ipv6 := geoip.IP.IPv6Addr
providers, err := singleton.GetDDNSProvidersFromProfiles(singleton.ServerList[clientID].DDNSProfiles, &ddns.IP{Ipv4Addr: ipv4, Ipv6Addr: ipv6}) providers, err := singleton.GetDDNSProvidersFromProfiles(server.DDNSProfiles, &ddns.IP{Ipv4Addr: ipv4, Ipv6Addr: ipv6})
if err == nil { if err == nil {
for _, provider := range providers { for _, provider := range providers {
go func(provider *ddns.Provider) { go func(provider *ddns.Provider) {
@ -232,23 +239,22 @@ func (s *NezhaHandler) ReportGeoIP(c context.Context, r *pb.GeoIP) (*pb.GeoIP, e
} }
// 发送IP变动通知 // 发送IP变动通知
if singleton.ServerList[clientID].GeoIP != nil && singleton.Conf.EnableIPChangeNotification && if server.GeoIP != nil && singleton.Conf.EnableIPChangeNotification &&
((singleton.Conf.Cover == model.ConfigCoverAll && !singleton.Conf.IgnoredIPNotificationServerIDs[clientID]) || ((singleton.Conf.Cover == model.ConfigCoverAll && !singleton.Conf.IgnoredIPNotificationServerIDs[clientID]) ||
(singleton.Conf.Cover == model.ConfigCoverIgnoreAll && singleton.Conf.IgnoredIPNotificationServerIDs[clientID])) && (singleton.Conf.Cover == model.ConfigCoverIgnoreAll && singleton.Conf.IgnoredIPNotificationServerIDs[clientID])) &&
singleton.ServerList[clientID].GeoIP.IP.Join() != "" && server.GeoIP.IP.Join() != "" &&
joinedIP != "" && joinedIP != "" &&
singleton.ServerList[clientID].GeoIP.IP != geoip.IP { server.GeoIP.IP != geoip.IP {
singleton.SendNotification(singleton.Conf.IPChangeNotificationGroupID, singleton.SendNotification(singleton.Conf.IPChangeNotificationGroupID,
fmt.Sprintf( fmt.Sprintf(
"[%s] %s, %s => %s", "[%s] %s, %s => %s",
singleton.Localizer.T("IP Changed"), singleton.Localizer.T("IP Changed"),
singleton.ServerList[clientID].Name, singleton.IPDesensitize(singleton.ServerList[clientID].GeoIP.IP.Join()), server.Name, singleton.IPDesensitize(server.GeoIP.IP.Join()),
singleton.IPDesensitize(joinedIP), singleton.IPDesensitize(joinedIP),
), ),
nil) nil)
} }
singleton.ServerLock.RUnlock()
// 根据内置数据库查询 IP 地理位置 // 根据内置数据库查询 IP 地理位置
var ip string var ip string
@ -266,9 +272,7 @@ func (s *NezhaHandler) ReportGeoIP(c context.Context, r *pb.GeoIP) (*pb.GeoIP, e
geoip.CountryCode = location geoip.CountryCode = location
// 将地区码写入到 Host // 将地区码写入到 Host
singleton.ServerLock.Lock() server.GeoIP = &geoip
defer singleton.ServerLock.Unlock()
singleton.ServerList[clientID].GeoIP = &geoip
return &pb.GeoIP{Ip: nil, CountryCode: location}, nil return &pb.GeoIP{Ip: nil, CountryCode: location}, nil
} }