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  }