mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
fix:
This commit is contained in:
parent
ebb4c483d0
commit
cea179221c
2 changed files with 29 additions and 6 deletions
|
|
@ -1537,6 +1537,9 @@ func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) {
|
||||||
for _, traffic := range traffics {
|
for _, traffic := range traffics {
|
||||||
inbound_ids = append(inbound_ids, traffic.InboundId)
|
inbound_ids = append(inbound_ids, traffic.InboundId)
|
||||||
}
|
}
|
||||||
|
// Dedupe so an inbound hosting N expired clients is fetched and saved once
|
||||||
|
// per tick instead of N times across chunk boundaries.
|
||||||
|
inbound_ids = uniqueInts(inbound_ids)
|
||||||
// Chunked to stay under SQLite's bind-variable limit when many inbounds
|
// Chunked to stay under SQLite's bind-variable limit when many inbounds
|
||||||
// are touched in a single tick.
|
// are touched in a single tick.
|
||||||
for _, batch := range chunkInts(inbound_ids, sqliteMaxVars) {
|
for _, batch := range chunkInts(inbound_ids, sqliteMaxVars) {
|
||||||
|
|
@ -2523,6 +2526,23 @@ func uniqueNonEmptyStrings(in []string) []string {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// uniqueInts returns a deduplicated copy of in, preserving order of first occurrence.
|
||||||
|
func uniqueInts(in []int) []int {
|
||||||
|
if len(in) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
seen := make(map[int]struct{}, len(in))
|
||||||
|
out := make([]int, 0, len(in))
|
||||||
|
for _, v := range in {
|
||||||
|
if _, ok := seen[v]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[v] = struct{}{}
|
||||||
|
out = append(out, v)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// chunkStrings splits s into consecutive sub-slices of at most size elements.
|
// chunkStrings splits s into consecutive sub-slices of at most size elements.
|
||||||
// Returns nil for an empty input or non-positive size.
|
// Returns nil for an empty input or non-positive size.
|
||||||
func chunkStrings(s []string, size int) [][]string {
|
func chunkStrings(s []string, size int) [][]string {
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,11 @@ const (
|
||||||
hubControlQueue = 64 // Backlog for register/unregister bursts (page reloads, disconnect storms).
|
hubControlQueue = 64 // Backlog for register/unregister bursts (page reloads, disconnect storms).
|
||||||
|
|
||||||
// minBroadcastInterval throttles per-type broadcasts so cron storms or
|
// minBroadcastInterval throttles per-type broadcasts so cron storms or
|
||||||
// rapid mutations cannot drown the hub. Bursts collapse to one delivery.
|
// rapid mutations cannot drown the hub. Bursts within the interval are
|
||||||
// Only message types in throttledMessageTypes are gated — heartbeat and
|
// dropped (not coalesced); the next broadcast outside the window delivers
|
||||||
// real-time signals (status, traffic, client_stats, notification,
|
// the latest state. Only message types in throttledMessageTypes are gated —
|
||||||
// xray_state, invalidate) bypass this so they are never delayed.
|
// heartbeat and real-time signals (status, traffic, client_stats,
|
||||||
|
// notification, xray_state, invalidate) bypass this so they are never delayed.
|
||||||
minBroadcastInterval = 250 * time.Millisecond
|
minBroadcastInterval = 250 * time.Millisecond
|
||||||
|
|
||||||
// hubRestartAttempts caps panic-recovery restarts. After this many
|
// hubRestartAttempts caps panic-recovery restarts. After this many
|
||||||
|
|
@ -274,8 +275,10 @@ func trySend(c *Client, msg []byte) (ok bool) {
|
||||||
|
|
||||||
// Broadcast serializes payload and queues it for delivery to all clients.
|
// Broadcast serializes payload and queues it for delivery to all clients.
|
||||||
// If the serialized message exceeds maxMessageSize, an invalidate signal is
|
// If the serialized message exceeds maxMessageSize, an invalidate signal is
|
||||||
// queued instead so the frontend re-fetches via REST. Bursts of the same
|
// queued instead so the frontend re-fetches via REST. Broadcasts of throttled
|
||||||
// message type within minBroadcastInterval collapse to a single delivery.
|
// message types (see throttledMessageTypes) within minBroadcastInterval of
|
||||||
|
// the previous one are dropped — the next legitimate mutation will push the
|
||||||
|
// fresh state.
|
||||||
func (h *Hub) Broadcast(messageType MessageType, payload any) {
|
func (h *Hub) Broadcast(messageType MessageType, payload any) {
|
||||||
if h == nil || payload == nil || h.GetClientCount() == 0 {
|
if h == nil || payload == nil || h.GetClientCount() == 0 {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue