mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-21 19:31:28 +00:00
* fix(node): don't delete clients when a node reports an empty snapshot
A node snapshot that comes back with zero clients for an inbound the hub
still has clients on was treated as authoritative: SyncInbound strips
every link for that inbound, the orphan sweep marks the now-linkless
clients, and ReapSyncOrphans hard-deletes them once the grace period
elapses. But a zero-client snapshot is indistinguishable from a degraded
node — one that was just deleted, reset, restarted, or answered before
its config loaded. On 2026-10-04 this deleted clients across the whole
hub when a single node was removed.
Treat a zero-client snapshot for an inbound that still has clients as
non-authoritative: skip the link rebuild and the orphan sweep for that
inbound (the same handling a failed SyncInbound already gets) and wait
for a snapshot that carries clients. Removing a node's last client is
done from the hub (which updates links and pushes); a node still serving
other clients prunes a removed one through the existing partial path.
The two orphan tests that drove removal via an empty snapshot now drive
it via a partial snapshot (node alive, still serving another client),
the authoritative path. New tests in node_degraded_snapshot_test.go
cover the guard and its narrowness.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(node): keep hub settings on an empty node snapshot; address review
The empty-snapshot guard skipped only the link rebuild and orphan sweep,
but Phase A had already adopted the node's `{"clients":[]}` blob into
`inbounds.settings`. Reconcile builds each push from that blob, so the hub
kept re-pushing an empty client list and a reset/restarted node never got
its clients back — the guard fired forever. Phase A now refuses to blank the
settings of an inbound the hub still populates, so the hub stays
authoritative and reconcile re-pushes the real clients (recovery). A
node-side removal of the last client is therefore hub-authoritative by
design; the partial-snapshot path still prunes an inbound that reports other
clients.
- test: assert the inbound's settings survive an empty snapshot (fails
without the Phase A fix).
- drop TestSetRemoteTraffic_EmptySnapshotSurvivesReap (no branch the core
test doesn't already cover) and the duplicate orphanMark helper
(readOrphanMark already exists); trim the comment blocks to the 2-line
CLAUDE.md limit.
- fix a pre-existing -race/-shuffle flake: TestGetAmneziaWGLogs owned no DB
and relied on the ambient global one, which a sibling's dbtest cleanup
closes under shuffle, panicking on nil in amneziawgLogActivity. It now
owns a throwaway DB.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(node): re-push hub clients to a node that reports an empty snapshot
|
||
|---|---|---|
| .. | ||
| local.go | ||
| local_tuic_test.go | ||
| manager.go | ||
| manager_convergence_test.go | ||
| reconcile_skip_test.go | ||
| remote.go | ||
| remote_envelope_test.go | ||
| remote_mtls_test.go | ||
| remote_reset_test.go | ||
| remote_test.go | ||
| runtime.go | ||
| tls_client.go | ||
| tls_client_invalidate_test.go | ||
| tls_client_property_test.go | ||
| tls_client_test.go | ||
| tls_client_wire_test.go | ||