Browse Source

etcd: add consistent get

Xiang Li 11 years ago
parent
commit
4c116a5a01
2 changed files with 33 additions and 1 deletions
  1. 4 1
      etcdserver/v2_http_get.go
  2. 29 0
      etcdserver/v2_http_kv_test.go

+ 4 - 1
etcdserver/v2_http_get.go

@@ -26,8 +26,11 @@ import (
 )
 )
 
 
 func (p *participant) GetHandler(w http.ResponseWriter, req *http.Request) error {
 func (p *participant) GetHandler(w http.ResponseWriter, req *http.Request) error {
+	if req.FormValue("consistent") == "true" && !p.node.IsLeader() {
+		return p.redirect(w, req, p.node.Leader())
+	}
+
 	key := req.URL.Path[len("/v2/keys"):]
 	key := req.URL.Path[len("/v2/keys"):]
-	// TODO(xiangli): handle consistent get
 	recursive := (req.FormValue("recursive") == "true")
 	recursive := (req.FormValue("recursive") == "true")
 	sort := (req.FormValue("sorted") == "true")
 	sort := (req.FormValue("sorted") == "true")
 	waitIndex := req.FormValue("waitIndex")
 	waitIndex := req.FormValue("waitIndex")

+ 29 - 0
etcdserver/v2_http_kv_test.go

@@ -18,6 +18,7 @@ package etcdserver
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
@@ -668,6 +669,34 @@ func TestV2Get(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestConsistentGet(t *testing.T) {
+	defer afterTest(t)
+
+	noredirect := func(req *http.Request, via []*http.Request) error {
+		return errors.New("no redirect")
+	}
+
+	c := &testCluster{Size: 3}
+	c.Start()
+	defer c.Destroy()
+
+	u := fmt.Sprintf("%s%s", c.URL(1), "/v2/keys/foo?consistent=true")
+	ru := fmt.Sprintf("%s%s", c.URL(0), "/v2/keys/foo?consistent=true")
+	tc := testHttpClient{&http.Client{CheckRedirect: noredirect}}
+	resp, _ := tc.Get(u)
+	if resp.StatusCode != http.StatusTemporaryRedirect {
+		t.Errorf("status = %d, want %d", resp.StatusCode, http.StatusTemporaryRedirect)
+	}
+	location, err := resp.Location()
+	if err != nil {
+		t.Errorf("err = %v, want nil", err)
+	}
+	if location.String() != ru {
+		t.Errorf("location = %v, want %v", location.String(), ru)
+	}
+	resp.Body.Close()
+}
+
 func TestV2QuorumGet(t *testing.T) {
 func TestV2QuorumGet(t *testing.T) {
 	cl := testCluster{Size: 1}
 	cl := testCluster{Size: 1}
 	cl.Start()
 	cl.Start()