package servers import ( "sync" "time" ) // Servers contains a collection of servers to Postgres. type Servers struct { m sync.Mutex servers map[string]*Server opts []ServerOpt } // NewServers creates a collection of servers to Postgres. func NewServers(opts ...ServerOpt) *Servers { return &Servers{ servers: make(map[string]*Server), opts: opts, } } // GetServer returns established connection from a collection. func (s *Servers) GetServer(dsn string) (*Server, error) { s.m.Lock() defer s.m.Unlock() var err error var ok bool errCount := 0 // start at zero because we increment before doing work retries := 3 var server *Server for { if errCount++; errCount > retries { return nil, err } server, ok = s.servers[dsn] if !ok { server, err = NewServer(dsn, s.opts...) if err != nil { time.Sleep(time.Duration(errCount) * time.Second) continue } s.servers[dsn] = server } if err = server.Ping(); err != nil { delete(s.servers, dsn) time.Sleep(time.Duration(errCount) * time.Second) continue } break } return server, nil } // Close disconnects from all known servers. func (s *Servers) Close() { s.m.Lock() defer s.m.Unlock() for _, server := range s.servers { if err := server.Close(); err != nil { log.Errorf("failed to close connection to %q: %v", server, err) } } }