improved fast resolver

This commit is contained in:
Vladislav Yarmak
2025-09-23 23:02:17 +03:00
parent ee91c4383c
commit 872fc61a19
+24 -25
View File
@@ -16,11 +16,6 @@ type FastResolver struct {
upstreams []LookupNetIPer upstreams []LookupNetIPer
} }
type lookupReply struct {
addrs []netip.Addr
err error
}
func FastFromURLs(urls ...string) (*FastResolver, error) { func FastFromURLs(urls ...string) (*FastResolver, error) {
resolvers := make([]LookupNetIPer, 0, len(urls)) resolvers := make([]LookupNetIPer, 0, len(urls))
for i, u := range urls { for i, u := range urls {
@@ -40,33 +35,37 @@ func NewFastResolver(resolvers ...LookupNetIPer) *FastResolver {
} }
func (r FastResolver) LookupNetIP(ctx context.Context, network, host string) ([]netip.Addr, error) { func (r FastResolver) LookupNetIP(ctx context.Context, network, host string) ([]netip.Addr, error) {
ctx, cl := context.WithCancel(ctx) masterNotInterested := make(chan struct{})
drain := make(chan lookupReply, len(r.upstreams)) defer close(masterNotInterested)
errors := make(chan error)
success := make(chan []netip.Addr)
for _, res := range r.upstreams { for _, res := range r.upstreams {
go func(res LookupNetIPer) { go func(res LookupNetIPer) {
addrs, err := res.LookupNetIP(ctx, network, host) addrs, err := res.LookupNetIP(ctx, network, host)
drain <- lookupReply{addrs, err} if err == nil {
select {
case success <- addrs:
case <-masterNotInterested:
}
} else {
select {
case errors <-err:
case <-masterNotInterested:
}
}
}(res) }(res)
} }
i := 0
var resAddrs []netip.Addr
var resErr error var resErr error
for ; i < len(r.upstreams); i++ { for _ = range r.upstreams {
pair := <-drain select {
if pair.err != nil { case <-ctx.Done():
resErr = multierror.Append(resErr, pair.err) return nil, ctx.Err()
} else { case resAddrs := <-success:
cl() return resAddrs, nil
resAddrs = pair.addrs case err := <-errors:
resErr = nil resErr = multierror.Append(resErr, err)
break
} }
} }
go func() { return nil, resErr
for i = i + 1; i < len(r.upstreams); i++ {
<-drain
}
}()
return resAddrs, resErr
} }