Adopt xray-core's statsUserOnline policy and GetUsersStats RPC so online
detection is connection-based and IP limiting no longer requires an access
log. Falls back to the legacy traffic-delta onlines and access-log parsing
when the running core lacks the RPCs (Unimplemented), probed lazily per
process so a panel-driven version switch re-evaluates automatically.
Backend:
- xray/api.go: GetOnlineUsers (one GetUsersStats call returns all online
users and their source IPs) and IsUnimplementedErr.
- xray/process.go: per-process OnlineAPISupport tri-state capability cache.
- service/xray.go: ensureStatsPolicy injects statsUserOnline into every
policy level of the generated config; XrayService.GetOnlineUsers probes
and falls back.
- job/xray_traffic_job.go: union API onlines into the delta-derived active
set; bump last_online for idle-but-connected clients.
- job/check_client_ip_job.go: API-first IP source with shared enforcement;
live observations bypass the 30-min stale cutoff; access-log path
unchanged for older cores.
- service/setting.go: GetIpLimitEnable always true; new accessLogEnable
default for features that genuinely read the access log.
Frontend:
- Client form split into Basic and Config tabs; IP Limit and IP Log no
longer gated on access log; compact Auto Renew next to Start After First
Use; tabBasic/tabConfig added to all 13 locales.
- Xray logs button on the dashboard now gated on accessLogEnable.
Add a hot-apply layer that computes a diff between the old and new
generated config and applies only the changed parts through the Xray
gRPC HandlerService and RoutingService, avoiding a full process restart
whenever possible. A restart is still performed when sections that have
no reload API (log, dns, policy, observatory, ...) actually change.
Key additions:
- internal/xray/hot_diff.go: ComputeHotDiff with canonical-JSON
comparison (sorted keys, null=absent, full number precision) so UI
reformatting never triggers a spurious restart
- internal/xray/api.go: AddOutbound/DelOutbound, ApplyRoutingConfig,
GetBalancerInfo, SetBalancerTarget, TestRoute gRPC wrappers
- internal/web/service/xray.go: tryHotApply, ensureAPIServices,
GetBalancersStatus, OverrideBalancer, TestRoute service methods
- internal/web/controller/xray_setting.go: balancerStatus,
balancerOverride, routeTest API endpoints
- frontend: BalancersTab live-status/override columns, RouteTester
component, Restart button removed (Save now hot-applies)
- balancer-helpers.ts: syncObservatories never creates observatory
sections for random/roundRobin balancers (no reload API → restart)
- i18n: balancerLive/Override/routeTester keys added to all 13 locales