Browse Source

support consistent get

Xiang Li 12 years ago
parent
commit
a3545a7ffa
2 changed files with 32 additions and 21 deletions
  1. 15 21
      etcd_handlers.go
  2. 17 0
      util.go

+ 15 - 21
etcd_handlers.go

@@ -185,13 +185,12 @@ func DeleteHttpHandler(w http.ResponseWriter, req *http.Request) error {
 
 // Dispatch the command to leader
 func dispatch(c Command, w http.ResponseWriter, req *http.Request, etcd bool) error {
-
 	if r.State() == raft.Leader {
 		if body, err := r.Do(c); err != nil {
 			return err
 		} else {
 			if body == nil {
-				return etcdErr.NewError(etcdErr.EcodeRaftInternal, "Empty result from raft")
+				return etcdErr.NewError(300, "Empty result from raft")
 			} else {
 				body, _ := body.([]byte)
 				w.WriteHeader(http.StatusOK)
@@ -204,28 +203,14 @@ func dispatch(c Command, w http.ResponseWriter, req *http.Request, etcd bool) er
 		leader := r.Leader()
 		// current no leader
 		if leader == "" {
-			return etcdErr.NewError(etcdErr.EcodeRaftInternal, "")
-		}
-
-		// tell the client where is the leader
-		path := req.URL.Path
-
-		var url string
-
-		if etcd {
-			etcdAddr, _ := nameToEtcdURL(leader)
-			url = etcdAddr + path
-		} else {
-			raftAddr, _ := nameToRaftURL(leader)
-			url = raftAddr + path
+			return etcdErr.NewError(300, "")
 		}
 
-		debugf("Redirect to %s", url)
+		redirect(leader, etcd, w, req)
 
-		http.Redirect(w, req, url, http.StatusTemporaryRedirect)
 		return nil
 	}
-	return etcdErr.NewError(etcdErr.EcodeRaftInternal, "")
+	return etcdErr.NewError(300, "")
 }
 
 //--------------------------------------
@@ -282,7 +267,7 @@ func GetHttpHandler(w http.ResponseWriter, req *http.Request) error {
 
 	recursive := req.FormValue("recursive")
 
-	if req.FormValue("wait") == "true" {
+	if req.FormValue("wait") == "true" { // watch
 		command := &WatchCommand{
 			Key: key,
 		}
@@ -305,7 +290,16 @@ func GetHttpHandler(w http.ResponseWriter, req *http.Request) error {
 
 		event, err = command.Apply(r.Server)
 
-	} else {
+	} else { //get
+
+		if req.FormValue("consistent") == "true" {
+			if r.State() != raft.Leader {
+				leader := r.Leader()
+				redirect(leader, true, w, req)
+				return nil
+			}
+		}
+
 		command := &GetCommand{
 			Key: key,
 		}

+ 17 - 0
util.go

@@ -65,6 +65,23 @@ func startWebInterface() {
 // HTTP Utilities
 //--------------------------------------
 
+func redirect(node string, etcd bool, w http.ResponseWriter, req *http.Request) {
+	var url string
+	path := req.URL.Path
+
+	if etcd {
+		etcdAddr, _ := nameToEtcdURL(node)
+		url = etcdAddr + path
+	} else {
+		raftAddr, _ := nameToRaftURL(node)
+		url = raftAddr + path
+	}
+
+	debugf("Redirect to %s", url)
+
+	http.Redirect(w, req, url, http.StatusTemporaryRedirect)
+}
+
 func decodeJsonRequest(req *http.Request, data interface{}) error {
 	decoder := json.NewDecoder(req.Body)
 	if err := decoder.Decode(&data); err != nil && err != io.EOF {