Files
3x-ui/internal/web/runtime/runtime.go
T
MHSanaei b1fa76f9b6 fix(node): fully delete clients on nodes instead of only detaching them
Deleting a client on the master propagated to nodes via the detach
endpoint, which removes the client from that one inbound's settings but
deliberately keeps the client record. The node ended up with an
orphaned record that kept showing in its Clients view; the master and
node could never converge on a delete.

Full-delete and detach intent now travel separately: the Runtime
interface gains DeleteClient, which on Remote hits the node's
panel/api/clients/del endpoint (record, attachments, traffic; repeat
calls for a client on several inbounds of the same node are swallowed
as idempotent "not found"). Delete/DeleteByEmail/BulkDelete use it for
node inbounds, while Detach/BulkDetach keep the inbound-scoped detach
RPC so removing a client from one inbound never wipes it node-wide
(the #5543 guarantee is preserved and covered by tests). Bulk deletes
above the fold threshold still converge membership via reconcile; their
leftover node records can be cleaned with the node's delete-orphans
action.

Closes #5797
2026-07-05 20:28:26 +02:00

39 lines
1.5 KiB
Go

package runtime
import (
"context"
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
)
type Runtime interface {
Name() string
AddInbound(ctx context.Context, ib *model.Inbound) error
DelInbound(ctx context.Context, ib *model.Inbound) error
UpdateInbound(ctx context.Context, oldIb, newIb *model.Inbound) error
AddUser(ctx context.Context, ib *model.Inbound, userMap map[string]any) error
RemoveUser(ctx context.Context, ib *model.Inbound, email string) error
// Per-client operations that route through the node's clients API on
// Remote (instead of pushing the whole inbound) so the node applies
// per-user xray API calls without a DelInbound+AddInbound cycle.
UpdateUser(ctx context.Context, ib *model.Inbound, email string, payload model.Client) error
DeleteUser(ctx context.Context, ib *model.Inbound, email string) error
AddClient(ctx context.Context, ib *model.Inbound, client model.Client) error
// DeleteClient removes the client identified by email entirely from the
// runtime's own store: on Remote it hits the node's full-delete endpoint
// (record, attachments, traffic), unlike DeleteUser which only detaches
// from one inbound and leaves the node's client record behind. Local has
// no client store of its own, so it is a no-op there.
DeleteClient(ctx context.Context, email string) error
RestartXray(ctx context.Context) error
ResetClientTraffic(ctx context.Context, ib *model.Inbound, email string) error
ResetInboundTraffic(ctx context.Context, ib *model.Inbound) error
ResetAllTraffics(ctx context.Context) error
}