perf: prevent cron job overlap, auto-set GOMEMLIMIT, fix tgbot userStates race

cron: SkipIfStillRunning stops a slow 5s/10s job from overlapping itself and racing the shared xrayAPI (grpc conn leak) and the StatsLastValues map (fatal concurrent map write). memlimit: auto-detect a Go soft memory limit from XUI_MEMORY_LIMIT, the cgroup limit, or system RAM (about 90 percent); opt-in pprof via XUI_PPROF. tgbot: userStates now goes through a mutex-guarded store with TTL pruning (was raced by worker-pool and delayed-delete goroutines). check_client_ip: prefilter inbounds by settings LIKE limitIp instead of loading and JSON-parsing all of them every scan. minor: prune StatsLastValues, RateLimiter.lastSent, reportedRemoteTagConflict. docker-compose: document the memory knobs.
This commit is contained in:
MHSanaei
2026-06-22 02:48:58 +02:00
parent 679d2e1cca
commit 7d23a2c15b
11 changed files with 234 additions and 27 deletions
+13 -3
View File
@@ -476,9 +476,19 @@ func (s *Server) start(restartXray bool, startTgBot bool) (err error) {
}
service.StartTrafficWriter()
// cron.Recover wraps every job so a panic is logged and the scheduler keeps
// running, instead of the panic taking down the whole panel process.
s.cron = cron.New(cron.WithLocation(loc), cron.WithSeconds(), cron.WithChain(cron.Recover(cron.PrintfLogger(cronPanicLogger{}))))
// SkipIfStillRunning stops a slow job (e.g. the 5s traffic poll on a large
// install) from overlapping itself: two concurrent runs of the same job race
// the shared xrayAPI — leaking a grpc connection — and the StatsLastValues
// map, whose concurrent write is a fatal runtime throw cron.Recover can't
// catch. cron.Recover then logs any panic and keeps the scheduler alive.
s.cron = cron.New(
cron.WithLocation(loc),
cron.WithSeconds(),
cron.WithChain(
cron.SkipIfStillRunning(cron.DiscardLogger),
cron.Recover(cron.PrintfLogger(cronPanicLogger{})),
),
)
s.cron.Start()
// Wire the inbound-runtime manager once so InboundService can route