MCPcopy
hub / github.com/AdguardTeam/dnsproxy / ExchangeParallel

Function ExchangeParallel

upstream/parallel.go:24–66  ·  view source on GitHub ↗

ExchangeParallel returns the first successful response from one of u. It returns an error if all upstreams failed to exchange the request.

(ups []Upstream, req *dns.Msg)

Source from the content-addressed store, hash-verified

22// ExchangeParallel returns the first successful response from one of u. It
23// returns an error if all upstreams failed to exchange the request.
24func ExchangeParallel(ups []Upstream, req *dns.Msg) (reply *dns.Msg, resolved Upstream, err error) {
25 upsNum := len(ups)
26 switch upsNum {
27 case 0:
28 return nil, nil, ErrNoUpstreams
29 case 1:
30 return exchangeSingle(ups[0], req)
31 default:
32 // Go on.
33 }
34
35 resCh := make(chan any, upsNum)
36 for _, f := range ups {
37 // Use a copy to prevent data races, as [dns.Client] can modify the DNS
38 // request during the exchange.
39 //
40 // TODO(s.chzhen): Consider using buffer pool.
41 copyReq := req.Copy()
42 go exchangeAsync(f, copyReq, resCh)
43 }
44
45 errs := []error{}
46 for range ups {
47 var r *ExchangeAllResult
48 r, err = receiveAsyncResult(resCh)
49 if err != nil {
50 if !errors.Is(err, ErrNoReply) {
51 errs = append(errs, err)
52 }
53 } else {
54 return r.Resp, r.Upstream, nil
55 }
56 }
57
58 // TODO(e.burkov): Probably it's better to return the joined error from
59 // each upstream that returned no response, and get rid of multiple
60 // [errors.Is] calls. This will change the behavior though.
61 if len(errs) == 0 {
62 return nil, nil, errors.Error("none of upstream servers responded")
63 }
64
65 return nil, nil, errors.Join(errs...)
66}
67
68// exchangeSingle returns a successful response and resolver if a DNS lookup was
69// successful.

Callers 4

exchangeUpstreamsMethod · 0.92
replyFromUpstreamMethod · 0.92
TestExchangeParallelFunction · 0.85

Calls 4

exchangeSingleFunction · 0.85
exchangeAsyncFunction · 0.85
receiveAsyncResultFunction · 0.85
ErrorMethod · 0.45

Tested by 2

TestExchangeParallelFunction · 0.68

Used in the wild real call sites across dependent graphs

searching dependent graphs…