mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-11 23:26:07 +00:00
fix(node): stop one rejected inbound from starving a node's traffic sync
A legacy socks inbound (predating the socks-to-mixed protocol rename) fails the node's request validation when pushed. ReconcileNode aborted on the first failed inbound and syncOne then skipped the traffic snapshot entirely and never cleared ConfigDirty, so the whole node re-failed every tick and the master stopped deducting traffic for every client on that node, exactly as reported in #5685. Three-part fix: ReconcileNode now pushes every inbound and runs the delete sweep even past individual failures, returning the failures joined; syncOne logs a failed reconcile but continues with the traffic pull (dirty stays set, so reconcile retries and the merge stays in its conservative mode); and a migration renames legacy socks inbounds to mixed, which has an identical settings shape, removing the known trigger. Closes #5685
This commit is contained in:
@@ -82,6 +82,10 @@ func (s *InboundService) AnyNodePending(inboundIds []int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ReconcileNode pushes every inbound and sweeps undesired remote tags even when
|
||||
// individual operations fail, returning the failures joined: one inbound the
|
||||
// node rejects (e.g. a legacy protocol failing validation, #5685) must not
|
||||
// stall the rest of the node's config — or, via syncOne, its traffic sync.
|
||||
func (s *InboundService) ReconcileNode(ctx context.Context, rt *runtime.Remote, n *model.Node) error {
|
||||
if rt == nil || n == nil || n.Id <= 0 {
|
||||
return nil
|
||||
@@ -102,6 +106,7 @@ func (s *InboundService) ReconcileNode(ctx context.Context, rt *runtime.Remote,
|
||||
}
|
||||
prefix := nodeTagPrefix(&nodeID)
|
||||
desiredTags := make(map[string]struct{}, len(inbounds)*2)
|
||||
var errs []error
|
||||
for _, ib := range inbounds {
|
||||
desiredTags[ib.Tag] = struct{}{}
|
||||
// existsOnNode: does the node already report this inbound under any of the
|
||||
@@ -121,7 +126,7 @@ func (s *InboundService) ReconcileNode(ctx context.Context, rt *runtime.Remote,
|
||||
}
|
||||
}
|
||||
if _, err := rt.ReconcileInbound(ctx, ib, existsOnNode); err != nil {
|
||||
return fmt.Errorf("reconcile inbound %q: %w", ib.Tag, err)
|
||||
errs = append(errs, fmt.Errorf("reconcile inbound %q: %w", ib.Tag, err))
|
||||
}
|
||||
}
|
||||
// In "selected" sync mode the panel only manages the selected tags: the
|
||||
@@ -145,10 +150,10 @@ func (s *InboundService) ReconcileNode(ctx context.Context, rt *runtime.Remote,
|
||||
}
|
||||
}
|
||||
if err := rt.DelInbound(ctx, &model.Inbound{Tag: tag}); err != nil {
|
||||
return fmt.Errorf("reconcile delete %q: %w", tag, err)
|
||||
errs = append(errs, fmt.Errorf("reconcile delete %q: %w", tag, err))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
const resetGracePeriodMs int64 = 30000
|
||||
|
||||
Reference in New Issue
Block a user