fix(gost): remove single-node optimization to enable forwarder failover

The single-node bypass in hop.Select() was preventing FailFilter from
being applied when retry excludes reduced available nodes to one.
This caused failed forwarder nodes to keep being selected instead of
failing over to healthy alternatives.

FailFilter's built-in safety guard (len <= 1 returns as-is) ensures
the last remaining node is never permanently blocked.
This commit is contained in:
root
2026-02-05 02:14:37 +00:00
parent 1d19d68019
commit 7c898154b3
+3 -9
View File
@@ -204,17 +204,11 @@ func (p *chainHop) Select(ctx context.Context, opts ...hop.SelectOption) *chain.
return nodes[0]
}
// For single-node case: bypass selector/FailFilter to ensure availability.
// The marker system still works for metrics, but we don't block requests
// based on recent failures - the connection will be attempted regardless.
// This matches upstream go-gost/x behavior.
if len(nodes) == 1 {
return nodes[0]
}
// Multi-node case: use selector with FailFilter for proper failover.
// Use selector with FailFilter for proper failover.
// FailFilter will exclude recently-failed nodes, allowing traffic to
// be routed to healthy alternatives.
// Note: FailFilter has a safety guard (len <= 1 returns as-is) to ensure
// the last remaining node is never permanently blocked.
if s := p.options.selector; s != nil {
log.Debugf("[hop.Select] calling selector.Select with %d nodes", len(nodes))
if node := s.Select(ctx, nodes...); node != nil {