mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-22 12:36:07 +00:00
fix(online): scope online status per node instead of a global union
The inbounds page and Nodes page checked each client's email against a single deduped union of every node's online clients, so a client connected to one node showed as online on every inbound across every node. The local online set was also derived from the email-keyed client_traffics.last_online column, which remote-node syncs bump too, leaking remote-only clients onto local inbounds. Track online clients per node: the local panel's own xray clients under key 0 (derived from live traffic-poll deltas via RefreshLocalOnline, kept in memory and independent of the shared last_online column) and each remote node under its id. Add GetOnlineClientsByNode plus a /clients/onlinesByNode endpoint and onlineByNode WS field; node.go and the inbounds rollup now scope online by node. The flat GetOnlineClients union is kept for client-centric and total-count views (Clients page, dashboard, telegram). Closes #4809
This commit is contained in:
+13
-9
@@ -3259,6 +3259,13 @@ func (s *InboundService) GetOnlineClients() []string {
|
||||
return p.GetOnlineClients()
|
||||
}
|
||||
|
||||
func (s *InboundService) GetOnlineClientsByNode() map[int][]string {
|
||||
if p == nil {
|
||||
return map[int][]string{}
|
||||
}
|
||||
return p.GetOnlineClientsByNode()
|
||||
}
|
||||
|
||||
func (s *InboundService) SetNodeOnlineClients(nodeID int, emails []string) {
|
||||
if p != nil {
|
||||
p.SetNodeOnlineClients(nodeID, emails)
|
||||
@@ -3285,16 +3292,13 @@ func (s *InboundService) GetClientsLastOnline() (map[string]int64, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *InboundService) RefreshOnlineClientsFromMap(lastOnlineMap map[string]int64) {
|
||||
now := time.Now().UnixMilli()
|
||||
newOnlineClients := make([]string, 0, len(lastOnlineMap))
|
||||
for email, lastOnline := range lastOnlineMap {
|
||||
if now-lastOnline < onlineGracePeriodMs {
|
||||
newOnlineClients = append(newOnlineClients, email)
|
||||
}
|
||||
}
|
||||
// RefreshLocalOnlineClients folds the emails active on this panel's own
|
||||
// xray this poll into the local online set, applying the grace window and
|
||||
// pruning stale entries. Pass nil to only prune. See xray.Process for why
|
||||
// the local set is kept separate from the shared last_online column.
|
||||
func (s *InboundService) RefreshLocalOnlineClients(activeEmails []string) {
|
||||
if p != nil {
|
||||
p.SetOnlineClients(newOnlineClients)
|
||||
p.RefreshLocalOnline(activeEmails, time.Now().UnixMilli(), onlineGracePeriodMs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user