mirror of
https://github.com/LBRYFoundation/reflector.go.git
synced 2025-08-23 17:27:25 +00:00
107 lines
2.8 KiB
Go
107 lines
2.8 KiB
Go
package cluster
|
|
|
|
import (
|
|
"io/ioutil"
|
|
baselog "log"
|
|
"os"
|
|
"os/signal"
|
|
"strconv"
|
|
"sync"
|
|
"syscall"
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
"github.com/lbryio/lbry.go/crypto"
|
|
"github.com/lbryio/lbry.go/errors"
|
|
"github.com/lbryio/reflector.go/cluster"
|
|
|
|
"github.com/hashicorp/serf/serf"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type Cluster struct {
|
|
s *serf.Serf
|
|
eventCh <-chan serf.Event
|
|
}
|
|
|
|
func New() {
|
|
c := &Cluster{}
|
|
var err error
|
|
|
|
nodeName := crypto.RandString(12)
|
|
clusterAddr := "127.0.0.1:" + strconv.Itoa(clusterPort)
|
|
if args[0] == clusterStart {
|
|
c.s, c.eventCh, err = cluster.Connect(nodeName, clusterAddr, clusterPort)
|
|
} else {
|
|
c.s, c.eventCh, err = cluster.Connect(nodeName, clusterAddr, clusterPort+1+int(crypto.RandInt64(1000)))
|
|
}
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer c.Leave()
|
|
|
|
shutdownCh := make(chan struct{})
|
|
var shutdownWg sync.WaitGroup
|
|
|
|
shutdownWg.Add(1)
|
|
go func() {
|
|
defer shutdownWg.Done()
|
|
for {
|
|
select {
|
|
case event := <-eventCh:
|
|
spew.Dump(event)
|
|
switch event.EventType() {
|
|
case serf.EventMemberJoin, serf.EventMemberFailed, serf.EventMemberLeave:
|
|
memberEvent := event.(serf.MemberEvent)
|
|
if event.EventType() == serf.EventMemberJoin && len(memberEvent.Members) == 1 && memberEvent.Members[0].Name == nodeName {
|
|
// ignore event from my own joining of the cluster
|
|
} else {
|
|
//spew.Dump(c.Members())
|
|
alive := getAliveMembers(c.Members())
|
|
log.Printf("%s: my hash range is now %d of %d\n", nodeName, getHashRangeStart(nodeName, alive), len(alive))
|
|
// figure out my new hash range based on the start and the number of alive members
|
|
// get hashes in that range that need announcing
|
|
// announce them
|
|
// if more than one node is announcing each hash, figure out how to deal with last_announced_at so both nodes dont announce the same thing at the same time
|
|
}
|
|
}
|
|
case <-shutdownCh:
|
|
log.Debugln("shutting down event dumper")
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
|
|
interruptChan := make(chan os.Signal, 1)
|
|
signal.Notify(interruptChan, os.Interrupt, syscall.SIGTERM)
|
|
<-interruptChan
|
|
log.Debugln("received interrupt")
|
|
close(shutdownCh)
|
|
log.Debugln("waiting for threads to finish")
|
|
shutdownWg.Wait()
|
|
log.Debugln("shutting down main thread")
|
|
}
|
|
|
|
func Connect(nodeName, addr string, port int) (*serf.Serf, <-chan serf.Event, error) {
|
|
conf := serf.DefaultConfig()
|
|
conf.MemberlistConfig.BindPort = port
|
|
conf.MemberlistConfig.AdvertisePort = port
|
|
conf.NodeName = nodeName
|
|
|
|
nullLogger := baselog.New(ioutil.Discard, "", 0)
|
|
conf.Logger = nullLogger
|
|
|
|
eventCh := make(chan serf.Event)
|
|
conf.EventCh = eventCh
|
|
|
|
cluster, err := serf.Create(conf)
|
|
if err != nil {
|
|
return nil, nil, errors.Prefix("couldn't create cluster", err)
|
|
}
|
|
|
|
_, err = cluster.Join([]string{addr}, true)
|
|
if err != nil {
|
|
log.Warnf("couldn't join cluster, starting own: %v\n", err)
|
|
}
|
|
|
|
return cluster, eventCh, nil
|
|
}
|