mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-18 09:10:57 +00:00
fix: prevent online clients from randomly disappearing from panel UI (#4387)
* fix: prevent online clients from randomly disappearing from panel UI Online status was determined solely by whether a client transferred bytes in the current 5-second polling window. The online list was completely replaced each cycle, so idle-but-connected clients with no traffic delta in that window were dropped from the UI. Now online status is computed from lastOnline DB timestamps with a 5-second grace period via RefreshOnlineClientsFromMap(), so clients remain visible across idle polling windows. Closes #4384 * fix: extend online client grace period to survive idle poll cycles The 5s grace period equalled the traffic-poll interval, so a client whose Xray stats reported a zero delta for one cycle was still dropped on the very next tick. Bump to 20s (~4 polls) so idle-but-connected sessions stay visible across momentary counter gaps without lingering long after a real disconnect. Refs #4384 --------- Co-authored-by: MHSanaei <ho3ein.sanaei@gmail.com>
This commit is contained in:
@@ -87,10 +87,6 @@ func (j *NodeTrafficSyncJob) Run() {
|
||||
return
|
||||
}
|
||||
|
||||
online := j.inboundService.GetOnlineClients()
|
||||
if online == nil {
|
||||
online = []string{}
|
||||
}
|
||||
lastOnline, err := j.inboundService.GetClientsLastOnline()
|
||||
if err != nil {
|
||||
logger.Warning("node traffic sync: get last-online failed:", err)
|
||||
@@ -98,6 +94,13 @@ func (j *NodeTrafficSyncJob) Run() {
|
||||
if lastOnline == nil {
|
||||
lastOnline = map[string]int64{}
|
||||
}
|
||||
|
||||
j.inboundService.RefreshOnlineClientsFromMap(lastOnline)
|
||||
|
||||
online := j.inboundService.GetOnlineClients()
|
||||
if online == nil {
|
||||
online = []string{}
|
||||
}
|
||||
websocket.BroadcastTraffic(map[string]any{
|
||||
"onlineClients": online,
|
||||
"lastOnlineMap": lastOnline,
|
||||
|
||||
@@ -77,10 +77,6 @@ func (j *XrayTrafficJob) Run() {
|
||||
// a missing/null onlineClients field as "no update", so without this the
|
||||
// "everyone went offline" transition was silently dropped — stale online
|
||||
// users lingered in the list and the online filter kept showing them.
|
||||
onlineClients := j.inboundService.GetOnlineClients()
|
||||
if onlineClients == nil {
|
||||
onlineClients = []string{}
|
||||
}
|
||||
lastOnlineMap, err := j.inboundService.GetClientsLastOnline()
|
||||
if err != nil {
|
||||
logger.Warning("get clients last online failed:", err)
|
||||
@@ -88,6 +84,17 @@ func (j *XrayTrafficJob) Run() {
|
||||
if lastOnlineMap == nil {
|
||||
lastOnlineMap = make(map[string]int64)
|
||||
}
|
||||
|
||||
// Determine online clients from lastOnline timestamps with a 5-second
|
||||
// grace period instead of just the current 5-second traffic poll. This
|
||||
// prevents idle-but-connected clients from randomly disappearing from
|
||||
// the UI between polling windows.
|
||||
j.inboundService.RefreshOnlineClientsFromMap(lastOnlineMap)
|
||||
|
||||
onlineClients := j.inboundService.GetOnlineClients()
|
||||
if onlineClients == nil {
|
||||
onlineClients = []string{}
|
||||
}
|
||||
websocket.BroadcastTraffic(map[string]any{
|
||||
"traffics": traffics,
|
||||
"clientTraffics": clientTraffics,
|
||||
|
||||
Reference in New Issue
Block a user