github.com/code-to-go/safepool.lib@v0.0.0-20221205180519-ee25e63c226e/pool/connect.go (about) 1 package pool 2 3 import ( 4 "bytes" 5 "fmt" 6 "math" 7 "math/rand" 8 "path" 9 "time" 10 11 "github.com/code-to-go/safepool.lib/core" 12 "github.com/code-to-go/safepool.lib/transport" 13 14 "github.com/sirupsen/logrus" 15 ) 16 17 func pingExchanger(e transport.Exchanger, pool string, data []byte) (time.Duration, error) { 18 start := time.Now() 19 name := path.Join(pool, fmt.Sprintf(pingName, start.UnixMilli())) 20 err := e.Write(name, bytes.NewBuffer(data)) 21 if err != nil { 22 return 0, err 23 } 24 25 var buf bytes.Buffer 26 err = e.Read(name, nil, &buf) 27 if err != nil { 28 return 0, err 29 } 30 e.Delete(name) 31 32 if bytes.Equal(data, buf.Bytes()) { 33 return time.Since(start), nil 34 } else { 35 return 0, err 36 } 37 } 38 39 func (p *Pool) createExchangers(configs []transport.Config) { 40 for _, e := range p.exchangers { 41 e.Close() 42 } 43 p.exchangers = nil 44 45 for _, c := range configs { 46 e, err := transport.NewExchanger(c) 47 if core.IsErr(err, "cannot connect to exchange %s: %v", c) { 48 continue 49 } 50 p.exchangers = append(p.exchangers, e) 51 } 52 } 53 54 func (p *Pool) findPrimary() { 55 min := time.Duration(math.MaxInt64) 56 57 data := make([]byte, 4192) 58 rand.Seed(time.Now().Unix()) 59 rand.Read(data) 60 61 p.e = nil 62 for _, e := range p.exchangers { 63 ping, err := pingExchanger(e, p.Name, data) 64 if err != nil { 65 logrus.Warnf("no connection to %v", e) 66 continue 67 } 68 if ping < min { 69 min = ping 70 p.e = e 71 } 72 } 73 } 74 75 func (p *Pool) connectSafe(name string, configs []transport.Config) error { 76 p.createExchangers(configs) 77 p.findPrimary() 78 if p.e == nil { 79 logrus.Warnf("no available exchange for domain %s", p.Name) 80 return ErrNoExchange 81 } else { 82 return nil 83 } 84 }