discovery: store size inside /[cluster]/config
parent
00d1daaf1e
commit
6081311db5
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalidURL = errors.New("discovery: invalid URL")
|
ErrInvalidURL = errors.New("discovery: invalid URL")
|
||||||
ErrBadCluster = errors.New("discovery: bad key/value inside cluster")
|
ErrBadSizeKey = errors.New("discovery: size key is bad")
|
||||||
ErrSizeNotFound = errors.New("discovery: size key not found")
|
ErrSizeNotFound = errors.New("discovery: size key not found")
|
||||||
ErrTokenNotFound = errors.New("discovery: token not found")
|
ErrTokenNotFound = errors.New("discovery: token not found")
|
||||||
ErrDuplicateID = errors.New("discovery: found duplicate id")
|
ErrDuplicateID = errors.New("discovery: found duplicate id")
|
||||||
|
@ -69,26 +69,35 @@ func (d *discovery) createSelf() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *discovery) checkCluster() (client.Nodes, int, error) {
|
func (d *discovery) checkCluster() (client.Nodes, int, error) {
|
||||||
resp, err := d.c.Get(d.cluster)
|
configKey := path.Join("/", d.cluster, "config")
|
||||||
|
// find cluster size
|
||||||
|
resp, err := d.c.Get(path.Join(configKey, "size"))
|
||||||
|
if err != nil {
|
||||||
|
if err == client.ErrKeyNoExist {
|
||||||
|
return nil, 0, ErrSizeNotFound
|
||||||
|
}
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
size, err := strconv.Atoi(resp.Node.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, ErrBadSizeKey
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err = d.c.Get(d.cluster)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
nodes := resp.Node.Nodes
|
nodes := make(client.Nodes, 0)
|
||||||
|
// append non-config keys to nodes
|
||||||
|
for _, n := range resp.Node.Nodes {
|
||||||
|
if !strings.HasPrefix(n.Key, configKey) {
|
||||||
|
nodes = append(nodes, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
snodes := SortableNodes{nodes}
|
snodes := SortableNodes{nodes}
|
||||||
sort.Sort(snodes)
|
sort.Sort(snodes)
|
||||||
|
|
||||||
// find cluster size
|
|
||||||
if nodes[0].Key != path.Join("/", d.cluster, "size") {
|
|
||||||
return nil, 0, ErrSizeNotFound
|
|
||||||
}
|
|
||||||
size, err := strconv.Atoi(nodes[0].Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, ErrBadCluster
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove size key from nodes
|
|
||||||
nodes = nodes[1:]
|
|
||||||
|
|
||||||
// find self position
|
// find self position
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
if nodes[i].Key == d.selfKey() {
|
if nodes[i].Key == d.selfKey() {
|
||||||
|
|
|
@ -25,7 +25,7 @@ func TestCheckCluster(t *testing.T) {
|
||||||
{
|
{
|
||||||
// self is in the size range
|
// self is in the size range
|
||||||
client.Nodes{
|
client.Nodes{
|
||||||
{Key: "/1000/size", Value: "3", CreatedIndex: 1},
|
{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
|
||||||
{Key: self, CreatedIndex: 2},
|
{Key: self, CreatedIndex: 2},
|
||||||
{Key: "/1000/2", CreatedIndex: 3},
|
{Key: "/1000/2", CreatedIndex: 3},
|
||||||
{Key: "/1000/3", CreatedIndex: 4},
|
{Key: "/1000/3", CreatedIndex: 4},
|
||||||
|
@ -37,7 +37,7 @@ func TestCheckCluster(t *testing.T) {
|
||||||
{
|
{
|
||||||
// self is in the size range
|
// self is in the size range
|
||||||
client.Nodes{
|
client.Nodes{
|
||||||
{Key: "/1000/size", Value: "3", CreatedIndex: 1},
|
{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
|
||||||
{Key: "/1000/2", CreatedIndex: 2},
|
{Key: "/1000/2", CreatedIndex: 2},
|
||||||
{Key: "/1000/3", CreatedIndex: 3},
|
{Key: "/1000/3", CreatedIndex: 3},
|
||||||
{Key: self, CreatedIndex: 4},
|
{Key: self, CreatedIndex: 4},
|
||||||
|
@ -49,7 +49,7 @@ func TestCheckCluster(t *testing.T) {
|
||||||
{
|
{
|
||||||
// self is out of the size range
|
// self is out of the size range
|
||||||
client.Nodes{
|
client.Nodes{
|
||||||
{Key: "/1000/size", Value: "3", CreatedIndex: 1},
|
{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
|
||||||
{Key: "/1000/2", CreatedIndex: 2},
|
{Key: "/1000/2", CreatedIndex: 2},
|
||||||
{Key: "/1000/3", CreatedIndex: 3},
|
{Key: "/1000/3", CreatedIndex: 3},
|
||||||
{Key: "/1000/4", CreatedIndex: 4},
|
{Key: "/1000/4", CreatedIndex: 4},
|
||||||
|
@ -61,7 +61,7 @@ func TestCheckCluster(t *testing.T) {
|
||||||
{
|
{
|
||||||
// self is not in the cluster
|
// self is not in the cluster
|
||||||
client.Nodes{
|
client.Nodes{
|
||||||
{Key: "/1000/size", Value: "3", CreatedIndex: 1},
|
{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
|
||||||
{Key: "/1000/2", CreatedIndex: 2},
|
{Key: "/1000/2", CreatedIndex: 2},
|
||||||
{Key: "/1000/3", CreatedIndex: 3},
|
{Key: "/1000/3", CreatedIndex: 3},
|
||||||
},
|
},
|
||||||
|
@ -70,7 +70,7 @@ func TestCheckCluster(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
client.Nodes{
|
client.Nodes{
|
||||||
{Key: "/1000/size", Value: "3", CreatedIndex: 1},
|
{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
|
||||||
{Key: "/1000/2", CreatedIndex: 2},
|
{Key: "/1000/2", CreatedIndex: 2},
|
||||||
{Key: "/1000/3", CreatedIndex: 3},
|
{Key: "/1000/3", CreatedIndex: 3},
|
||||||
{Key: "/1000/4", CreatedIndex: 4},
|
{Key: "/1000/4", CreatedIndex: 4},
|
||||||
|
@ -81,34 +81,33 @@ func TestCheckCluster(t *testing.T) {
|
||||||
{
|
{
|
||||||
// bad size key
|
// bad size key
|
||||||
client.Nodes{
|
client.Nodes{
|
||||||
{Key: "/1000/size", Value: "bad", CreatedIndex: 1},
|
{Key: "/1000/config/size", Value: "bad", CreatedIndex: 1},
|
||||||
},
|
},
|
||||||
ErrBadCluster,
|
ErrBadSizeKey,
|
||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// no size key
|
// no size key
|
||||||
client.Nodes{
|
client.Nodes{},
|
||||||
{Key: self, CreatedIndex: 1},
|
|
||||||
},
|
|
||||||
ErrSizeNotFound,
|
ErrSizeNotFound,
|
||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
resp := &client.Response{
|
rs := make([]*client.Response, 0)
|
||||||
Node: &client.Node{
|
if len(tt.nodes) > 0 {
|
||||||
Key: cluster,
|
rs = append(rs, &client.Response{Node: tt.nodes[0]})
|
||||||
Nodes: tt.nodes,
|
rs = append(rs, &client.Response{
|
||||||
},
|
Node: &client.Node{
|
||||||
|
Key: cluster,
|
||||||
|
Nodes: tt.nodes,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
c := &clientWithResp{rs: rs}
|
||||||
c := &clientWithResp{
|
|
||||||
rs: []*client.Response{resp},
|
|
||||||
}
|
|
||||||
|
|
||||||
d := discovery{cluster: cluster, id: 1, c: c}
|
d := discovery{cluster: cluster, id: 1, c: c}
|
||||||
|
|
||||||
ns, size, err := d.checkCluster()
|
ns, size, err := d.checkCluster()
|
||||||
if err != tt.werr {
|
if err != tt.werr {
|
||||||
t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
|
t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
|
||||||
|
@ -277,7 +276,7 @@ func (c *clientWithResp) Create(key string, value string, ttl time.Duration) (*c
|
||||||
|
|
||||||
func (c *clientWithResp) Get(key string) (*client.Response, error) {
|
func (c *clientWithResp) Get(key string) (*client.Response, error) {
|
||||||
if len(c.rs) == 0 {
|
if len(c.rs) == 0 {
|
||||||
return &client.Response{}, nil
|
return &client.Response{}, client.ErrKeyNoExist
|
||||||
}
|
}
|
||||||
r := c.rs[0]
|
r := c.rs[0]
|
||||||
c.rs = c.rs[1:]
|
c.rs = c.rs[1:]
|
||||||
|
|
Loading…
Reference in New Issue