Rework federation to be synchronous, and add tests
This commit is contained in:
parent
a67f9b43d1
commit
914d2bfc61
7 changed files with 675 additions and 274 deletions
1
go.mod
1
go.mod
|
@ -8,6 +8,7 @@ require (
|
|||
github.com/lbryio/lbry.go/v2 v2.7.2-0.20210625145058-2b155597bf57
|
||||
github.com/olivere/elastic/v7 v7.0.24
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
||||
golang.org/x/text v0.3.6
|
||||
google.golang.org/genproto v0.0.0-20210524171403-669157292da3 // indirect
|
||||
|
|
|
@ -22,5 +22,13 @@ var (
|
|||
Help: "Histogram of query times",
|
||||
Buckets: HistogramBuckets,
|
||||
}, []string{"method"})
|
||||
PeersKnown = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "peers_known",
|
||||
Help: "Number of peers we know about.",
|
||||
})
|
||||
PeersSubscribed = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "peers_subbed",
|
||||
Help: "Number of peers that are subscribed to us.",
|
||||
})
|
||||
)
|
||||
|
||||
|
|
29
main.go
29
main.go
|
@ -4,14 +4,12 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
pb "github.com/lbryio/hub/protobuf/go"
|
||||
"github.com/lbryio/hub/server"
|
||||
"github.com/lbryio/lbry.go/v2/extras/util"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -26,20 +24,21 @@ func main() {
|
|||
ctxWCancel, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
l, err := net.Listen("tcp", ":"+args.Port)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
}
|
||||
|
||||
s := server.MakeHubServer(ctxWCancel, args)
|
||||
pb.RegisterHubServer(s.GrpcServer, s)
|
||||
reflection.Register(s.GrpcServer)
|
||||
|
||||
log.Printf("listening on %s\n", l.Addr().String())
|
||||
log.Println(s.Args)
|
||||
if err := s.GrpcServer.Serve(l); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
s.Run()
|
||||
//l, err := net.Listen("tcp", ":"+args.Port)
|
||||
//if err != nil {
|
||||
// log.Fatalf("failed to listen: %v", err)
|
||||
//}
|
||||
//
|
||||
//pb.RegisterHubServer(s.GrpcServer, s)
|
||||
//reflection.Register(s.GrpcServer)
|
||||
//
|
||||
//log.Printf("listening on %s\n", l.Addr().String())
|
||||
//log.Println(s.Args)
|
||||
//if err := s.GrpcServer.Serve(l); err != nil {
|
||||
// log.Fatalf("failed to serve: %v", err)
|
||||
//}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -22,15 +22,15 @@ type Args struct {
|
|||
UDPPort string
|
||||
EsHost string
|
||||
EsPort string
|
||||
DisableEs bool
|
||||
PrometheusPort string
|
||||
EsIndex string
|
||||
Debug bool
|
||||
RefreshDelta int
|
||||
CacheTTL int
|
||||
PeerFile string
|
||||
Country string
|
||||
StartPeerAdder bool
|
||||
DisableEs bool
|
||||
Debug bool
|
||||
LoadPeers bool
|
||||
StartPrometheus bool
|
||||
StartUDP bool
|
||||
WritePeers bool
|
||||
|
@ -48,7 +48,7 @@ const (
|
|||
DefaultCacheTTL = 5
|
||||
DefaultPeerFile = "peers.txt"
|
||||
DefaultCountry = "US"
|
||||
DefaultStartPeerAdder = true
|
||||
DefaultLoadPeers = true
|
||||
DefaultStartPrometheus = true
|
||||
DefaultStartUDP = true
|
||||
DefaultWritePeers = true
|
||||
|
@ -83,8 +83,6 @@ func ParseArgs(searchRequest *pb.SearchRequest) *Args {
|
|||
|
||||
serveCmd := parser.NewCommand("serve", "start the hub server")
|
||||
searchCmd := parser.NewCommand("search", "claim search")
|
||||
debug := parser.Flag("", "debug", &argparse.Options{Required: false, Help: "enable debug logging", Default: false})
|
||||
disableEs := parser.Flag("", "disable-es", &argparse.Options{Required: false, Help: "Disable elastic search, for running/testing independently", Default: false})
|
||||
|
||||
host := parser.String("", "rpchost", &argparse.Options{Required: false, Help: "RPC host", Default: DefaultHost})
|
||||
port := parser.String("", "rpcport", &argparse.Options{Required: false, Help: "RPC port", Default: DefaultPort})
|
||||
|
@ -97,7 +95,10 @@ func ParseArgs(searchRequest *pb.SearchRequest) *Args {
|
|||
cacheTTL := parser.Int("", "cachettl", &argparse.Options{Required: false, Help: "Cache TTL in minutes", Default: DefaultCacheTTL})
|
||||
peerFile := parser.String("", "peerfile", &argparse.Options{Required: false, Help: "Initial peer file for federation", Default: DefaultPeerFile})
|
||||
country := parser.String("", "country", &argparse.Options{Required: false, Help: "Country this node is running in. Default US.", Default: DefaultCountry})
|
||||
startPeerAdder := parser.Flag("", "start-peer-adder", &argparse.Options{Required: false, Help: "Start peer adder service", Default: DefaultStartPeerAdder})
|
||||
|
||||
debug := parser.Flag("", "debug", &argparse.Options{Required: false, Help: "enable debug logging", Default: false})
|
||||
disableEs := parser.Flag("", "disable-es", &argparse.Options{Required: false, Help: "Disable elastic search, for running/testing independently", Default: false})
|
||||
loadPeers := parser.Flag("", "load-peers", &argparse.Options{Required: false, Help: "load peers from disk at startup", Default: DefaultLoadPeers})
|
||||
startPrometheus := parser.Flag("", "start-prometheus", &argparse.Options{Required: false, Help: "Start prometheus server", Default: DefaultStartPrometheus})
|
||||
startUdp := parser.Flag("", "start-udp", &argparse.Options{Required: false, Help: "Start UDP ping server", Default: DefaultStartUDP})
|
||||
writePeers := parser.Flag("", "write-peers", &argparse.Options{Required: false, Help: "Write peer to disk as we learn about them", Default: DefaultWritePeers})
|
||||
|
@ -125,15 +126,15 @@ func ParseArgs(searchRequest *pb.SearchRequest) *Args {
|
|||
EsHost: *esHost,
|
||||
EsPort: *esPort,
|
||||
UDPPort: *udpPort,
|
||||
DisableEs: *disableEs,
|
||||
PrometheusPort: *prometheusPort,
|
||||
EsIndex: *esIndex,
|
||||
Debug: *debug,
|
||||
RefreshDelta: *refreshDelta,
|
||||
CacheTTL: *cacheTTL,
|
||||
PeerFile: *peerFile,
|
||||
Country: *country,
|
||||
StartPeerAdder: *startPeerAdder,
|
||||
DisableEs: *disableEs,
|
||||
Debug: *debug,
|
||||
LoadPeers: *loadPeers,
|
||||
StartPrometheus: *startPrometheus,
|
||||
StartUDP: *startUdp,
|
||||
WritePeers: *writePeers,
|
||||
|
|
|
@ -6,19 +6,14 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/lbryio/hub/internal/metrics"
|
||||
pb "github.com/lbryio/hub/protobuf/go"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// peerAddMsg is an internal structure for use in the channel communicating
|
||||
// to the peerAdder gorountine.
|
||||
type peerAddMsg struct {
|
||||
msg *pb.ServerMessage
|
||||
ping bool
|
||||
}
|
||||
|
||||
// FederatedServer hold relevant information about peers that we known about.
|
||||
type FederatedServer struct {
|
||||
Address string
|
||||
|
@ -26,29 +21,56 @@ type FederatedServer struct {
|
|||
Ts time.Time
|
||||
}
|
||||
|
||||
var (
|
||||
localHosts = map[string]bool{
|
||||
"127.0.0.1": true,
|
||||
"0.0.0.0": true,
|
||||
"localhost": true,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
// peerKey takes a ServerMessage object and returns the key that for that peer
|
||||
// in our peer table.
|
||||
func peerKey(msg *pb.ServerMessage) string {
|
||||
return msg.Address + ":" + msg.Port
|
||||
}
|
||||
|
||||
func (s *Server) incNumPeers() {
|
||||
atomic.AddInt64(s.NumPeerServers, 1)
|
||||
}
|
||||
|
||||
func (s *Server) decNumPeers() {
|
||||
atomic.AddInt64(s.NumPeerServers, -1)
|
||||
}
|
||||
|
||||
func (s *Server) getNumPeers() int64 {
|
||||
return *s.NumPeerServers
|
||||
}
|
||||
|
||||
func (s *Server) incNumSubs() {
|
||||
atomic.AddInt64(s.NumPeerSubs, 1)
|
||||
}
|
||||
|
||||
func (s *Server) decNumSubs() {
|
||||
atomic.AddInt64(s.NumPeerSubs, -1)
|
||||
}
|
||||
|
||||
func (s *Server) getNumSubs() int64 {
|
||||
return *s.NumPeerSubs
|
||||
}
|
||||
|
||||
// loadPeers takes the arguments given to the hub at startup and loads the
|
||||
// previously known peers from disk and verifies their existence before
|
||||
// storing them as known peers. Returns a map of peerKey -> object
|
||||
func loadPeers(args *Args) map[string]*FederatedServer {
|
||||
localHosts := map[string]bool {
|
||||
"127.0.0.1": true,
|
||||
"0.0.0.0": true,
|
||||
"localhost": true,
|
||||
}
|
||||
servers := make(map[string]*FederatedServer)
|
||||
peerFile := args.PeerFile
|
||||
port := args.Port
|
||||
func (s *Server) loadPeers() error {
|
||||
peerFile := s.Args.PeerFile
|
||||
port := s.Args.Port
|
||||
|
||||
f, err := os.Open(peerFile)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return map[string]*FederatedServer{}
|
||||
return err
|
||||
}
|
||||
scanner := bufio.NewScanner(f)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
@ -68,25 +90,164 @@ func loadPeers(args *Args) map[string]*FederatedServer {
|
|||
continue
|
||||
}
|
||||
// If the peer is us, skip
|
||||
log.Println(args)
|
||||
log.Println(ipPort)
|
||||
if ipPort[1] == port && localHosts[ipPort[0]] {
|
||||
log.Println("Self peer, skipping ...")
|
||||
continue
|
||||
}
|
||||
server := &FederatedServer{
|
||||
srvMsg := &pb.ServerMessage{
|
||||
Address: ipPort[0],
|
||||
Port: ipPort[1],
|
||||
Ts: time.Now(),
|
||||
}
|
||||
log.Println("pinging peer", server)
|
||||
if helloPeer(server, args) {
|
||||
servers[line] = server
|
||||
log.Printf("pinging peer %+v\n", srvMsg)
|
||||
err := s.addPeer(srvMsg, true)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Returning from loadPeers")
|
||||
return servers
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// getFastestPeer determines the fastest peer in its list of peers by sending
|
||||
// out udp pings and seeing who responds first. This is currently not
|
||||
// implemented and just returns the first peer.
|
||||
func (s *Server) getFastestPeer() *FederatedServer {
|
||||
var fastestPeer *FederatedServer
|
||||
|
||||
s.PeerServers.Range(func(_, v interface{}) bool {
|
||||
fastestPeer = v.(*FederatedServer)
|
||||
return false
|
||||
})
|
||||
|
||||
return fastestPeer
|
||||
}
|
||||
|
||||
// subscribeToFastestPeer is a convenience function to find and subscribe to
|
||||
// the fastest peer we know about.
|
||||
func (s *Server) subscribeToFastestPeer() {
|
||||
peer := s.getFastestPeer()
|
||||
if peer != nil {
|
||||
err := s.subscribeToPeer(peer)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
} else {
|
||||
log.Println("No peers found, not subscribed to any.")
|
||||
}
|
||||
}
|
||||
|
||||
// subscribeToPeer subscribes us to a peer to we'll get updates about their
|
||||
// known peers.
|
||||
func (s *Server) subscribeToPeer(peer *FederatedServer) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
conn, err := grpc.DialContext(ctx,
|
||||
peer.Address+":"+peer.Port,
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithBlock(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
msg := &pb.ServerMessage{
|
||||
Address: s.Args.Host,
|
||||
Port: s.Args.Port,
|
||||
}
|
||||
|
||||
c := pb.NewHubClient(conn)
|
||||
|
||||
log.Printf("%s:%s subscribing to %+v\n", s.Args.Host, s.Args.Port, peer)
|
||||
_, err = c.PeerSubscribe(ctx, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Subscribed = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// helloPeer takes a peer to say hello to and sends a hello message
|
||||
// containing all the peers we know about and information about us.
|
||||
// This is used to confirm existence of peers on start and let them
|
||||
// know about us. Returns the response from the server on success,
|
||||
// nil otherwise.
|
||||
func (s *Server) helloPeer(server *FederatedServer) (*pb.HelloMessage, error) {
|
||||
log.Println("In helloPeer")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
conn, err := grpc.DialContext(ctx,
|
||||
server.Address+":"+server.Port,
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithBlock(),
|
||||
)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
c := pb.NewHubClient(conn)
|
||||
|
||||
msg := &pb.HelloMessage{
|
||||
Port: s.Args.Port,
|
||||
Host: s.Args.Host,
|
||||
Servers: []*pb.ServerMessage{},
|
||||
}
|
||||
|
||||
log.Printf("%s:%s saying hello to %+v\n", s.Args.Host, s.Args.Port, server)
|
||||
res, err := c.Hello(ctx, msg)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Println(res)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// writePeers writes our current known peers to disk.
|
||||
func (s *Server) writePeers() {
|
||||
if !s.Args.WritePeers {
|
||||
return
|
||||
}
|
||||
f, err := os.Create(s.Args.PeerFile)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
writer := bufio.NewWriter(f)
|
||||
|
||||
s.PeerServers.Range(func(k, _ interface{}) bool {
|
||||
key, ok := k.(string)
|
||||
if !ok {
|
||||
log.Println("Failed to cast key when writing peers: ", k)
|
||||
return true
|
||||
}
|
||||
line := key + "\n"
|
||||
_, err := writer.WriteString(line)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// notifyPeer takes a peer to notify and a new peer we just learned about
|
||||
|
@ -120,115 +281,8 @@ func notifyPeer(peerToNotify *FederatedServer, newPeer *FederatedServer) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// helloPeer takes a peer to say hello to and sends a hello message
|
||||
// containing all the peers we know about and information about us.
|
||||
// This is used to confirm existence of peers on start and let them
|
||||
// know about us. Returns true is call was successful, false otherwise.
|
||||
func helloPeer(server *FederatedServer, args *Args) bool {
|
||||
log.Println("In helloPeer")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
conn, err := grpc.DialContext(ctx,
|
||||
server.Address+":"+server.Port,
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithBlock(),
|
||||
)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return false
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
|
||||
c := pb.NewHubClient(conn)
|
||||
|
||||
msg := &pb.HelloMessage{
|
||||
Port: args.Port,
|
||||
Host: args.Host,
|
||||
Servers: []*pb.ServerMessage{},
|
||||
}
|
||||
res, err := c.Hello(ctx, msg)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return false
|
||||
}
|
||||
|
||||
log.Println(res)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// writePeers writes our current known peers to disk.
|
||||
func (s *Server) writePeers() {
|
||||
if !s.Args.WritePeers {
|
||||
return
|
||||
}
|
||||
failedCreat := "WARNING: Peer writer failed to create peer file, it's still running but may not be working!"
|
||||
failedWrite := "WARNING: Peer writer failed to write a line, it's still running but may not be working!"
|
||||
failedFlush := "WARNING: Peer writer failed to flush, it's still running but may not be working!"
|
||||
failedClose := "WARNING: Peer writer failed to close the peer file, it's still running but may not be working!"
|
||||
f, err := os.Create(s.Args.PeerFile)
|
||||
if err != nil {
|
||||
log.Println(failedCreat)
|
||||
log.Println(err)
|
||||
}
|
||||
writer := bufio.NewWriter(f)
|
||||
|
||||
for _, peer := range s.Servers {
|
||||
line := peer.Address + ":" + peer.Port + "\n"
|
||||
_, err := writer.WriteString(line)
|
||||
if err != nil {
|
||||
log.Println(failedWrite)
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
log.Println(failedFlush)
|
||||
log.Println(err)
|
||||
}
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
log.Println(failedClose)
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// peerAdder is a goroutine which listens for new peers added and then
|
||||
// optionally checks if they're online and adds them to our map of
|
||||
// peers in a thread safe manner.
|
||||
func (s *Server) peerAdder(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case chanMsg := <-s.peerChannel:
|
||||
msg := chanMsg.msg
|
||||
ping := chanMsg.ping
|
||||
|
||||
k := msg.Address + ":" + msg.Port
|
||||
if _, ok := s.Servers[k]; !ok {
|
||||
newServer := &FederatedServer{
|
||||
Address: msg.Address,
|
||||
Port: msg.Port,
|
||||
Ts: time.Now(),
|
||||
}
|
||||
if !ping || helloPeer(newServer, s.Args) {
|
||||
s.Servers[k] = newServer
|
||||
s.writePeers()
|
||||
s.notifyPeerSubs(newServer)
|
||||
}
|
||||
} else {
|
||||
s.Servers[k].Ts = time.Now()
|
||||
}
|
||||
case <-ctx.Done():
|
||||
log.Println("context finished, peerAdder shutting down.")
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// notifyPeerSubs takes a new peer server we just learned about and notifies
|
||||
// all the peers that have subscribed to us about it.
|
||||
func (s *Server) notifyPeerSubs(newServer *FederatedServer) {
|
||||
var unsubscribe []string
|
||||
s.PeerSubs.Range(func(k, v interface{}) bool {
|
||||
|
@ -254,37 +308,96 @@ func (s *Server) notifyPeerSubs(newServer *FederatedServer) {
|
|||
})
|
||||
|
||||
for _, key := range unsubscribe {
|
||||
s.decNumSubs()
|
||||
metrics.PeersSubscribed.Dec()
|
||||
s.PeerSubs.Delete(key)
|
||||
}
|
||||
}
|
||||
|
||||
// addPeer is an internal function to add a peer to this hub.
|
||||
func (s *Server) addPeer(msg *pb.ServerMessage, ping bool) {
|
||||
s.peerChannel <- &peerAddMsg{msg, ping}
|
||||
// addPeer takes a new peer as a pb.ServerMessage, optionally checks to see
|
||||
// if they're online, and adds them to our list of peer. If we're not currently
|
||||
// subscribed to a peer, it will also subscribe to it.
|
||||
func (s *Server) addPeer(msg *pb.ServerMessage, ping bool) error {
|
||||
if s.Args.Port == msg.Port &&
|
||||
(localHosts[msg.Address] || msg.Address == s.Args.Host) {
|
||||
log.Printf("%s:%s addPeer: Self peer, skipping...\n", s.Args.Host, s.Args.Port)
|
||||
return nil
|
||||
}
|
||||
k := peerKey(msg)
|
||||
newServer := &FederatedServer{
|
||||
Address: msg.Address,
|
||||
Port: msg.Port,
|
||||
Ts: time.Now(),
|
||||
}
|
||||
log.Printf("%s:%s adding peer %+v\n", s.Args.Host, s.Args.Port, msg)
|
||||
if oldServer, loaded := s.PeerServers.LoadOrStore(k, newServer); !loaded {
|
||||
if ping {
|
||||
_, err := s.helloPeer(newServer)
|
||||
if err != nil {
|
||||
s.PeerServers.Delete(k)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
s.incNumPeers()
|
||||
metrics.PeersKnown.Inc()
|
||||
s.writePeers()
|
||||
s.notifyPeerSubs(newServer)
|
||||
|
||||
// If aren't subscribed to a server yet, subscribe to
|
||||
// this one.
|
||||
if !s.Subscribed {
|
||||
err := s.subscribeToPeer(newServer)
|
||||
if err != nil {
|
||||
s.PeerServers.Delete(k)
|
||||
return err
|
||||
} else {
|
||||
s.Subscribed = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
oldServerCast, ok := oldServer.(*FederatedServer)
|
||||
// This shouldn't happen, but if it does, I guess delete the key
|
||||
// and try adding this one since it's new.
|
||||
if !ok {
|
||||
log.Println("Error casting map value: ", oldServer)
|
||||
s.PeerServers.Delete(k)
|
||||
return s.addPeer(msg, ping)
|
||||
}
|
||||
oldServerCast.Ts = time.Now()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mergeFederatedServers is an internal convenience function to add a list of
|
||||
// peers.
|
||||
func (s *Server) mergeFederatedServers(servers []*pb.ServerMessage) {
|
||||
for _, srvMsg := range servers {
|
||||
s.peerChannel <- &peerAddMsg{srvMsg, false}
|
||||
err := s.addPeer(srvMsg, false)
|
||||
// This shouldn't happen because we're not pinging them.
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// makeHelloMessage makes a message for this hub to call the Hello endpoint
|
||||
// on another hub.
|
||||
func (s *Server) makeHelloMessage() *pb.HelloMessage {
|
||||
n := len(s.Servers)
|
||||
servers := make([]*pb.ServerMessage, n)
|
||||
servers := make([]*pb.ServerMessage, 0, 10)
|
||||
|
||||
var i = 0
|
||||
for _, v := range s.Servers {
|
||||
servers[i] = &pb.ServerMessage{
|
||||
Address: v.Address,
|
||||
Port: v.Port,
|
||||
}
|
||||
i += 1
|
||||
s.PeerServers.Range(func(_, v interface{}) bool {
|
||||
peer, ok := v.(*FederatedServer)
|
||||
if !ok {
|
||||
log.Println("Failed to cast value in makeHelloMessage", v)
|
||||
return true
|
||||
}
|
||||
servers = append(servers, &pb.ServerMessage{
|
||||
Address: peer.Address,
|
||||
Port: peer.Port,
|
||||
})
|
||||
return true
|
||||
})
|
||||
|
||||
return &pb.HelloMessage{
|
||||
Port: s.Args.Port,
|
||||
|
|
|
@ -8,9 +8,11 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/lbryio/hub/internal/metrics"
|
||||
pb "github.com/lbryio/hub/protobuf/go"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// lineCountFile takes a fileName and counts the number of lines in it.
|
||||
|
@ -40,9 +42,7 @@ func removeFile(fileName string) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestPeerAdder tests the peer adder goroutine.
|
||||
func TestPeerAdder(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
func makeDefaultArgs() *Args {
|
||||
args := &Args{
|
||||
CmdType: ServeCmd,
|
||||
Host: DefaultHost,
|
||||
|
@ -50,20 +50,28 @@ func TestPeerAdder(t *testing.T) {
|
|||
EsHost: DefaultEsHost,
|
||||
EsPort: DefaultEsPort,
|
||||
UDPPort: DefaultUdpPort,
|
||||
DisableEs: true,
|
||||
PrometheusPort: DefaultPrometheusPort,
|
||||
EsIndex: DefaultEsIndex,
|
||||
Debug: true,
|
||||
RefreshDelta: DefaultRefreshDelta,
|
||||
CacheTTL: DefaultCacheTTL,
|
||||
PeerFile: DefaultPeerFile,
|
||||
Country: DefaultCountry,
|
||||
StartPeerAdder: false,
|
||||
DisableEs: true,
|
||||
Debug: true,
|
||||
LoadPeers: false,
|
||||
StartPrometheus: false,
|
||||
StartUDP: false,
|
||||
WritePeers: false,
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
// TestAddPeer tests the ability to add peers
|
||||
func TestAddPeer(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
args := makeDefaultArgs()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
want int
|
||||
|
@ -81,67 +89,47 @@ func TestPeerAdder(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T){
|
||||
server := MakeHubServer(ctx, args)
|
||||
ctxWCancel, cancel := context.WithCancel(ctx)
|
||||
server.Subscribed = true
|
||||
metrics.PeersKnown.Set(0)
|
||||
|
||||
go server.peerAdder(ctxWCancel)
|
||||
for i := 0; i < 10; i++ {
|
||||
var msg *peerAddMsg
|
||||
var msg *pb.ServerMessage
|
||||
if strings.Contains(tt.name, "1 unique") {
|
||||
msg = &peerAddMsg{
|
||||
msg: &pb.ServerMessage{
|
||||
msg = &pb.ServerMessage{
|
||||
Address: "1.1.1.1",
|
||||
Port: "50051",
|
||||
},
|
||||
ping: false,
|
||||
}
|
||||
} else {
|
||||
msg = &peerAddMsg{
|
||||
msg: &pb.ServerMessage{
|
||||
Address: fmt.Sprintf("%d.%d.%d.%d", i, i, i, i),
|
||||
x := i + 1
|
||||
msg = &pb.ServerMessage{
|
||||
Address: fmt.Sprintf("%d.%d.%d.%d", x, x, x, x),
|
||||
Port: "50051",
|
||||
},
|
||||
ping: false,
|
||||
}
|
||||
}
|
||||
server.peerChannel <- msg
|
||||
//log.Printf("Adding peer %+v\n", msg)
|
||||
err := server.addPeer(msg, false)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
// Have to give it a second to update peers since it's in
|
||||
// another thread.
|
||||
time.Sleep(time.Second)
|
||||
got := len(server.Servers)
|
||||
}
|
||||
var m = &dto.Metric{}
|
||||
if err := metrics.PeersKnown.Write(m); err != nil {
|
||||
t.Errorf("Error getting metrics %+v\n", err)
|
||||
}
|
||||
got := int(*m.Gauge.Value)
|
||||
if got != tt.want {
|
||||
t.Errorf("len(server.Servers) = %d, want %d", got, tt.want)
|
||||
t.Errorf("len(server.PeerServers) = %d, want %d\n", got, tt.want)
|
||||
}
|
||||
cancel()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestPeerWriter tests that the peerAdder goroutine writes the peer file
|
||||
// properly when set to do so.
|
||||
// TestPeerWriter tests that peers get written properly
|
||||
func TestPeerWriter(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
args := &Args{
|
||||
CmdType: ServeCmd,
|
||||
Host: DefaultHost,
|
||||
Port: DefaultPort,
|
||||
EsHost: DefaultEsHost,
|
||||
EsPort: DefaultEsPort,
|
||||
UDPPort: DefaultUdpPort,
|
||||
DisableEs: true,
|
||||
PrometheusPort: DefaultPrometheusPort,
|
||||
EsIndex: DefaultEsIndex,
|
||||
Debug: true,
|
||||
RefreshDelta: DefaultRefreshDelta,
|
||||
CacheTTL: DefaultCacheTTL,
|
||||
PeerFile: DefaultPeerFile,
|
||||
Country: DefaultCountry,
|
||||
StartPeerAdder: false,
|
||||
StartPrometheus: false,
|
||||
StartUDP: false,
|
||||
WritePeers: true,
|
||||
}
|
||||
args := makeDefaultArgs()
|
||||
args.WritePeers = true
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -160,40 +148,279 @@ func TestPeerWriter(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T){
|
||||
server := MakeHubServer(ctx, args)
|
||||
ctxWCancel, cancel := context.WithCancel(ctx)
|
||||
server.Subscribed = true
|
||||
|
||||
go server.peerAdder(ctxWCancel)
|
||||
for i := 0; i < 10; i++ {
|
||||
var msg *peerAddMsg
|
||||
var msg *pb.ServerMessage
|
||||
if strings.Contains(tt.name, "1 unique") {
|
||||
msg = &peerAddMsg{
|
||||
msg: &pb.ServerMessage{
|
||||
msg = &pb.ServerMessage{
|
||||
Address: "1.1.1.1",
|
||||
Port: "50051",
|
||||
},
|
||||
ping: false,
|
||||
}
|
||||
} else {
|
||||
msg = &peerAddMsg{
|
||||
msg: &pb.ServerMessage{
|
||||
msg = &pb.ServerMessage{
|
||||
Address: fmt.Sprintf("%d.%d.%d.%d", i, i, i, i),
|
||||
Port: "50051",
|
||||
},
|
||||
ping: false,
|
||||
}
|
||||
}
|
||||
server.peerChannel <- msg
|
||||
//log.Printf("Adding peer %+v\n", msg)
|
||||
err := server.addPeer(msg, false)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
// Have to give it a second to update peers since it's in
|
||||
// another thread.
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
//log.Println("Counting lines...")
|
||||
got := lineCountFile(server.Args.PeerFile)
|
||||
if got != tt.want {
|
||||
t.Errorf("len(server.Servers) = %d, want %d", got, tt.want)
|
||||
t.Errorf("lineCountFile(peers.txt) = %d, want %d", got, tt.want)
|
||||
}
|
||||
cancel()
|
||||
})
|
||||
}
|
||||
|
||||
removeFile(args.PeerFile)
|
||||
}
|
||||
|
||||
// TestAddPeerEndpoint tests the ability to add peers
|
||||
func TestAddPeerEndpoint(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
args := makeDefaultArgs()
|
||||
args2 := makeDefaultArgs()
|
||||
args2.Port = "50052"
|
||||
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
wantServerOne int64
|
||||
wantServerTwo int64
|
||||
} {
|
||||
{
|
||||
// outside -> server1.AddPeer(server2, ping=true) : server1 = 1, server2 = 0
|
||||
// server1 -> server2.Hello(server1) : server1 = 1, server2 = 0
|
||||
// server2 -> server2.addPeer(server1, ping=false) : server1 = 1, server2 = 1
|
||||
// server2 -> server1.PeerSubscribe(server2) : server1 = 1, server2 = 1
|
||||
// server1 <- server2.makeHelloMessage() : server1 = 1, server2 = 1
|
||||
// server1.notifyPeer() : server1 = 1, server2 = 1
|
||||
// server1 -> server2.AddPeer(server2) : server1 = 1, server2 = 1
|
||||
// server2 self peer, skipping : server1 = 1, server2 = 1
|
||||
// server1 -> server2.PeerSubscribe(server1) : server1 = 1, server2 = 1
|
||||
name: "Add 1 peer",
|
||||
wantServerOne: 1,
|
||||
wantServerTwo: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T){
|
||||
server := MakeHubServer(ctx, args)
|
||||
server2 := MakeHubServer(ctx, args2)
|
||||
metrics.PeersKnown.Set(0)
|
||||
go server.Run()
|
||||
go server2.Run()
|
||||
//go server.Run()
|
||||
conn, err := grpc.Dial("localhost:"+args.Port,
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithBlock(),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %v", err)
|
||||
}
|
||||
|
||||
c := pb.NewHubClient(conn)
|
||||
|
||||
msg := &pb.ServerMessage{
|
||||
Address: "0.0.0.0",
|
||||
Port: "50052",
|
||||
}
|
||||
|
||||
_, err = c.AddPeer(context.Background(), msg)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
server.GrpcServer.GracefulStop()
|
||||
server2.GrpcServer.GracefulStop()
|
||||
got1 := server.getNumPeers()
|
||||
got2 := server2.getNumPeers()
|
||||
if got1 != tt.wantServerOne {
|
||||
t.Errorf("len(server.PeerServers) = %d, want %d\n", got1, tt.wantServerOne)
|
||||
}
|
||||
if got2 != tt.wantServerTwo {
|
||||
t.Errorf("len(server2.PeerServers) = %d, want %d\n", got2, tt.wantServerTwo)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestAddPeerEndpoint2 tests the ability to add peers
|
||||
func TestAddPeerEndpoint2(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
args := makeDefaultArgs()
|
||||
args2 := makeDefaultArgs()
|
||||
args3 := makeDefaultArgs()
|
||||
args2.Port = "50052"
|
||||
args3.Port = "50053"
|
||||
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
wantServerOne int64
|
||||
wantServerTwo int64
|
||||
wantServerThree int64
|
||||
} {
|
||||
{
|
||||
name: "Add 2 peers",
|
||||
wantServerOne: 2,
|
||||
wantServerTwo: 2,
|
||||
wantServerThree: 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T){
|
||||
server := MakeHubServer(ctx, args)
|
||||
server2 := MakeHubServer(ctx, args2)
|
||||
server3 := MakeHubServer(ctx, args3)
|
||||
metrics.PeersKnown.Set(0)
|
||||
go server.Run()
|
||||
go server2.Run()
|
||||
go server3.Run()
|
||||
conn, err := grpc.Dial("localhost:"+args.Port,
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithBlock(),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %v", err)
|
||||
}
|
||||
|
||||
c := pb.NewHubClient(conn)
|
||||
|
||||
msg := &pb.ServerMessage{
|
||||
Address: "0.0.0.0",
|
||||
Port: "50052",
|
||||
}
|
||||
|
||||
msg2 := &pb.ServerMessage{
|
||||
Address: "0.0.0.0",
|
||||
Port: "50053",
|
||||
}
|
||||
|
||||
_, err = c.AddPeer(context.Background(), msg)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
_, err = c.AddPeer(context.Background(), msg2)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
server.GrpcServer.GracefulStop()
|
||||
server2.GrpcServer.GracefulStop()
|
||||
server3.GrpcServer.GracefulStop()
|
||||
got1 := server.getNumPeers()
|
||||
got2 := server2.getNumPeers()
|
||||
got3 := server3.getNumPeers()
|
||||
if got1 != tt.wantServerOne {
|
||||
t.Errorf("len(server.PeerServers) = %d, want %d\n", got1, tt.wantServerOne)
|
||||
}
|
||||
if got2 != tt.wantServerTwo {
|
||||
t.Errorf("len(server2.PeerServers) = %d, want %d\n", got2, tt.wantServerTwo)
|
||||
}
|
||||
if got3 != tt.wantServerThree {
|
||||
t.Errorf("len(server3.PeerServers) = %d, want %d\n", got3, tt.wantServerThree)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TestAddPeerEndpoint3 tests the ability to add peers
|
||||
func TestAddPeerEndpoint3(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
args := makeDefaultArgs()
|
||||
args2 := makeDefaultArgs()
|
||||
args3 := makeDefaultArgs()
|
||||
args2.Port = "50052"
|
||||
args3.Port = "50053"
|
||||
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
wantServerOne int64
|
||||
wantServerTwo int64
|
||||
wantServerThree int64
|
||||
} {
|
||||
{
|
||||
name: "Add 1 peer to each",
|
||||
wantServerOne: 2,
|
||||
wantServerTwo: 2,
|
||||
wantServerThree: 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T){
|
||||
server := MakeHubServer(ctx, args)
|
||||
server2 := MakeHubServer(ctx, args2)
|
||||
server3 := MakeHubServer(ctx, args3)
|
||||
metrics.PeersKnown.Set(0)
|
||||
go server.Run()
|
||||
go server2.Run()
|
||||
go server3.Run()
|
||||
conn, err := grpc.Dial("localhost:"+args.Port,
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithBlock(),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %v", err)
|
||||
}
|
||||
conn2, err := grpc.Dial("localhost:50052",
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithBlock(),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %v", err)
|
||||
}
|
||||
|
||||
c := pb.NewHubClient(conn)
|
||||
c2 := pb.NewHubClient(conn2)
|
||||
|
||||
msg := &pb.ServerMessage{
|
||||
Address: "0.0.0.0",
|
||||
Port: "50052",
|
||||
}
|
||||
|
||||
msg2 := &pb.ServerMessage{
|
||||
Address: "0.0.0.0",
|
||||
Port: "50053",
|
||||
}
|
||||
|
||||
_, err = c.AddPeer(context.Background(), msg)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
_, err = c2.AddPeer(context.Background(), msg2)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
server.GrpcServer.GracefulStop()
|
||||
server2.GrpcServer.GracefulStop()
|
||||
server3.GrpcServer.GracefulStop()
|
||||
got1 := server.getNumPeers()
|
||||
got2 := server2.getNumPeers()
|
||||
got3 := server3.getNumPeers()
|
||||
if got1 != tt.wantServerOne {
|
||||
t.Errorf("len(server.PeerServers) = %d, want %d\n", got1, tt.wantServerOne)
|
||||
}
|
||||
if got2 != tt.wantServerTwo {
|
||||
t.Errorf("len(server2.PeerServers) = %d, want %d\n", got2, tt.wantServerTwo)
|
||||
}
|
||||
if got3 != tt.wantServerThree {
|
||||
t.Errorf("len(server3.PeerServers) = %d, want %d\n", got3, tt.wantServerThree)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"hash"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
|
@ -20,6 +21,7 @@ import (
|
|||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
|
@ -28,14 +30,16 @@ type Server struct {
|
|||
MultiSpaceRe *regexp.Regexp
|
||||
WeirdCharsRe *regexp.Regexp
|
||||
EsClient *elastic.Client
|
||||
Servers map[string]*FederatedServer
|
||||
QueryCache *ttlcache.Cache
|
||||
S256 *hash.Hash
|
||||
LastRefreshCheck time.Time
|
||||
RefreshDelta time.Duration
|
||||
NumESRefreshes int64
|
||||
PeerServers sync.Map //map[string]*FederatedServer
|
||||
NumPeerServers *int64
|
||||
PeerSubs sync.Map
|
||||
peerChannel chan *peerAddMsg
|
||||
NumPeerSubs *int64
|
||||
Subscribed bool
|
||||
pb.UnimplementedHubServer
|
||||
}
|
||||
|
||||
|
@ -83,14 +87,28 @@ func getVersion() string {
|
|||
'blockchain.address.unsubscribe'
|
||||
*/
|
||||
|
||||
func (s *Server) Run() {
|
||||
l, err := net.Listen("tcp", ":"+s.Args.Port)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
}
|
||||
|
||||
pb.RegisterHubServer(s.GrpcServer, s)
|
||||
reflection.Register(s.GrpcServer)
|
||||
|
||||
log.Printf("listening on %s\n", l.Addr().String())
|
||||
log.Println(s.Args)
|
||||
if err := s.GrpcServer.Serve(l); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// MakeHubServer takes the arguments given to a hub when it's started and
|
||||
// initializes everything. It loads information about previously known peers,
|
||||
// creates needed internal data structures, and initializes goroutines.
|
||||
func MakeHubServer(ctx context.Context, args *Args) *Server {
|
||||
grpcServer := grpc.NewServer(grpc.NumStreamWorkers(10))
|
||||
|
||||
peerChannel := make(chan *peerAddMsg)
|
||||
|
||||
multiSpaceRe, err := regexp.Compile(`\s{2,}`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -101,8 +119,6 @@ func MakeHubServer(ctx context.Context, args *Args) *Server {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
servers := loadPeers(args)
|
||||
|
||||
var client *elastic.Client
|
||||
if !args.DisableEs {
|
||||
esUrl := args.EsHost + ":" + args.EsPort
|
||||
|
@ -134,6 +150,11 @@ func MakeHubServer(ctx context.Context, args *Args) *Server {
|
|||
refreshDelta = time.Second * 0
|
||||
}
|
||||
|
||||
numPeers := new(int64)
|
||||
*numPeers = 0
|
||||
numSubs := new(int64)
|
||||
*numSubs = 0
|
||||
|
||||
s := &Server{
|
||||
GrpcServer: grpcServer,
|
||||
Args: args,
|
||||
|
@ -145,15 +166,14 @@ func MakeHubServer(ctx context.Context, args *Args) *Server {
|
|||
LastRefreshCheck: time.Now(),
|
||||
RefreshDelta: refreshDelta,
|
||||
NumESRefreshes: 0,
|
||||
Servers: servers,
|
||||
PeerServers: sync.Map{},
|
||||
NumPeerServers: numPeers,
|
||||
PeerSubs: sync.Map{},
|
||||
peerChannel: peerChannel,
|
||||
NumPeerSubs: numSubs,
|
||||
Subscribed: false,
|
||||
}
|
||||
|
||||
// Start up our background services
|
||||
if args.StartPeerAdder {
|
||||
go s.peerAdder(ctx)
|
||||
}
|
||||
if args.StartPrometheus {
|
||||
go s.prometheusEndpoint(s.Args.PrometheusPort, "metrics")
|
||||
}
|
||||
|
@ -165,6 +185,20 @@ func MakeHubServer(ctx context.Context, args *Args) *Server {
|
|||
}
|
||||
}()
|
||||
}
|
||||
// Load peers from disk and subscribe to one if there are any
|
||||
if args.LoadPeers {
|
||||
// We Subscribed to true, so we don't try subscribing to peers as we
|
||||
// add them, we'll find the best one after
|
||||
s.Subscribed = true
|
||||
err = s.loadPeers()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
// subscribe to the fastest peer we know (if there are any) for updates
|
||||
// about their peers.
|
||||
s.Subscribed = false
|
||||
s.subscribeToFastestPeer()
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
@ -182,6 +216,7 @@ func (s *Server) prometheusEndpoint(port string, endpoint string) {
|
|||
// The passed message includes information about the other hub, and all
|
||||
// of its peers which are added to the knowledge of this hub.
|
||||
func (s *Server) Hello(ctx context.Context, args *pb.HelloMessage) (*pb.HelloMessage, error) {
|
||||
metrics.RequestsCount.With(prometheus.Labels{"method": "hello"}).Inc()
|
||||
port := args.Port
|
||||
host := args.Host
|
||||
server := &FederatedServer{
|
||||
|
@ -191,7 +226,11 @@ func (s *Server) Hello(ctx context.Context, args *pb.HelloMessage) (*pb.HelloMes
|
|||
}
|
||||
log.Println(server)
|
||||
|
||||
s.addPeer(&pb.ServerMessage{Address: host, Port: port}, false)
|
||||
err := s.addPeer(&pb.ServerMessage{Address: host, Port: port}, false)
|
||||
// They just contacted us, so this shouldn't happen
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
s.mergeFederatedServers(args.Servers)
|
||||
s.writePeers()
|
||||
s.notifyPeerSubs(server)
|
||||
|
@ -202,21 +241,34 @@ func (s *Server) Hello(ctx context.Context, args *pb.HelloMessage) (*pb.HelloMes
|
|||
// PeerSubscribe adds a peer hub to the list of subscribers to update about
|
||||
// new peers.
|
||||
func (s *Server) PeerSubscribe(ctx context.Context, in *pb.ServerMessage) (*pb.StringValue, error) {
|
||||
metrics.RequestsCount.With(prometheus.Labels{"method": "peer_subscribe"}).Inc()
|
||||
var msg = "Success"
|
||||
peer := &FederatedServer{
|
||||
Address: in.Address,
|
||||
Port: in.Port,
|
||||
Ts: time.Now(),
|
||||
}
|
||||
|
||||
s.PeerSubs.Store(peerKey(in), peer)
|
||||
if _, loaded := s.PeerSubs.LoadOrStore(peerKey(in), peer); !loaded {
|
||||
s.incNumSubs()
|
||||
metrics.PeersSubscribed.Inc()
|
||||
} else {
|
||||
msg = "Already subscribed"
|
||||
}
|
||||
|
||||
return &pb.StringValue{Value: "Success"}, nil
|
||||
return &pb.StringValue{Value: msg}, nil
|
||||
}
|
||||
|
||||
// AddPeer is a grpc endpoint to tell this hub about another hub in the network.
|
||||
func (s *Server) AddPeer(ctx context.Context, args *pb.ServerMessage) (*pb.StringValue, error) {
|
||||
s.addPeer(args, true)
|
||||
return &pb.StringValue{Value: "Success!"}, nil
|
||||
metrics.RequestsCount.With(prometheus.Labels{"method": "add_peer"}).Inc()
|
||||
var msg = "Success"
|
||||
err := s.addPeer(args, true)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
msg = "Failed"
|
||||
}
|
||||
return &pb.StringValue{Value: msg}, err
|
||||
}
|
||||
|
||||
// Ping is a grpc endpoint that returns a short message.
|
||||
|
|
Loading…
Reference in a new issue