This is an automated email from the ASF dual-hosted git repository.

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-kie.git


The following commit(s) were added to refs/heads/master by this push:
     new 2720808  #109 client支持指定revision (#108)
2720808 is described below

commit 2720808ae136d483d42914397c6f3a0a7f9dfb23
Author: zhulijian <[email protected]>
AuthorDate: Mon Mar 2 17:01:46 2020 +0800

    #109 client支持指定revision (#108)
    
    * Improve client revision features
    
    Signed-off-by: zhulijian <[email protected]>
    
    * ut
---
 client/client.go      | 40 ++++++++++++++++++++++++++++------------
 client/client_test.go | 24 ++++++++++++++++--------
 client/options.go     | 20 +++++++++++++++-----
 3 files changed, 59 insertions(+), 25 deletions(-)

diff --git a/client/client.go b/client/client.go
index b70d465..422a537 100644
--- a/client/client.go
+++ b/client/client.go
@@ -25,6 +25,7 @@ import (
        "fmt"
        "net/http"
        "net/url"
+       "strconv"
        "strings"
 
        "github.com/apache/servicecomb-kie/pkg/common"
@@ -57,7 +58,7 @@ type Client struct {
        opts            Config
        cipher          security.Cipher
        c               *httpclient.Requests
-       CurrentRevision string
+       currentRevision int
 }
 
 //Config is the config of client
@@ -127,7 +128,7 @@ func (c *Client) Put(ctx context.Context, kv 
model.KVRequest, opts ...OpOption)
 }
 
 //Get get value of a key
-func (c *Client) Get(ctx context.Context, opts ...GetOption) 
(*model.KVResponse, error) {
+func (c *Client) Get(ctx context.Context, opts ...GetOption) 
(*model.KVResponse, int, error) {
        options := GetOptions{}
        for _, o := range opts {
                o(&options)
@@ -135,12 +136,14 @@ func (c *Client) Get(ctx context.Context, opts 
...GetOption) (*model.KVResponse,
        if options.Project == "" {
                options.Project = defaultProject
        }
-
+       if options.Revision == "" {
+               options.Revision = strconv.Itoa(c.currentRevision)
+       }
        var url string
        if options.Key != "" {
-               url = fmt.Sprintf("%s/%s/%s/%s/%s?revision=%s", 
c.opts.Endpoint, version, options.Project, APIPathKV, options.Key, 
c.CurrentRevision)
+               url = fmt.Sprintf("%s/%s/%s/%s/%s?revision=%s", 
c.opts.Endpoint, version, options.Project, APIPathKV, options.Key, 
options.Revision)
        } else {
-               url = fmt.Sprintf("%s/%s/%s/%s?revision=%s", c.opts.Endpoint, 
version, options.Project, APIPathKV, c.CurrentRevision)
+               url = fmt.Sprintf("%s/%s/%s/%s?revision=%s", c.opts.Endpoint, 
version, options.Project, APIPathKV, options.Revision)
        }
        if options.Wait != "" {
                url = url + "&wait=" + options.Wait
@@ -158,31 +161,39 @@ func (c *Client) Get(ctx context.Context, opts 
...GetOption) (*model.KVResponse,
        h := http.Header{}
        resp, err := c.c.Do(ctx, http.MethodGet, url, h, nil)
        if err != nil {
-               return nil, err
+               return nil, -1, err
+       }
+       responseRevision, err := 
strconv.Atoi(resp.Header.Get(common.HeaderRevision))
+       if err != nil {
+               responseRevision = -1
        }
        b := httputil.ReadBody(resp)
        if resp.StatusCode != http.StatusOK {
                if resp.StatusCode == http.StatusNotFound {
-                       return nil, ErrKeyNotExist
+                       return nil, responseRevision, ErrKeyNotExist
                }
                if resp.StatusCode == http.StatusNotModified {
-                       return nil, ErrNoChanges
+                       return nil, responseRevision, ErrNoChanges
                }
                openlogging.Error(MsgGetFailed, 
openlogging.WithTags(openlogging.Tags{
                        "k":      options.Key,
                        "status": resp.Status,
                        "body":   b,
                }))
-               return nil, fmt.Errorf(FmtGetFailed, options.Key, resp.Status, 
b)
+               return nil, responseRevision, fmt.Errorf(FmtGetFailed, 
options.Key, resp.Status, b)
+       } else if err != nil {
+               msg := fmt.Sprintf("get revision from response header failed 
when the request status is OK: %v", err)
+               openlogging.Error(msg)
+               return nil, responseRevision, fmt.Errorf(msg)
        }
        var kvs *model.KVResponse
        err = json.Unmarshal(b, &kvs)
        if err != nil {
                openlogging.Error("unmarshal kv failed:" + err.Error())
-               return nil, err
+               return nil, responseRevision, err
        }
-       c.CurrentRevision = resp.Header.Get(common.HeaderRevision)
-       return kvs, nil
+       c.currentRevision = responseRevision
+       return kvs, responseRevision, nil
 }
 
 //Summary get value by labels
@@ -261,3 +272,8 @@ func (c *Client) Delete(ctx context.Context, kvID, labelID 
string, opts ...OpOpt
        }
        return nil
 }
+
+//CurrentRevision return the current revision of kie, which is updated on the 
last get request
+func (c *Client) CurrentRevision() int {
+       return c.currentRevision
+}
diff --git a/client/client_test.go b/client/client_test.go
index b66a598..7c8fcd0 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -40,24 +40,32 @@ func TestClient_Put(t *testing.T) {
        _, err := c.Put(context.TODO(), kv, WithProject("client_test"))
        assert.NoError(t, err)
 
-       kvs, _ := c.Get(context.TODO(),
+       kvs, responseRevision, _ := c.Get(context.TODO(),
                WithKey("app.properties"),
                WithGetProject("client_test"),
                WithLabels(map[string]string{"service": "client"}))
        assert.GreaterOrEqual(t, len(kvs.Data), 1)
 
-       _, err = c.Get(context.TODO(),
+       _, _, err = c.Get(context.TODO(),
                WithGetProject("client_test"),
-               WithLabels(map[string]string{"service": "client"}))
+               WithLabels(map[string]string{"service": "client"}),
+               WithRevision(responseRevision))
        assert.Equal(t, ErrNoChanges, err)
 
-       _, err = c.Get(context.TODO(),
+       _, _, err = c.Get(context.TODO(),
+               WithGetProject("client_test"),
                WithLabels(map[string]string{"service": "client"}))
        assert.Error(t, err)
 
+       _, _, err = c.Get(context.TODO(),
+               WithGetProject("client_test"),
+               WithLabels(map[string]string{"service": "client"}),
+               WithRevision(c.CurrentRevision()-1))
+       assert.NoError(t, err)
+
        t.Run("long polling,wait 10s,change value,should return result", func(t 
*testing.T) {
                go func() {
-                       kvs, err = c.Get(context.TODO(),
+                       kvs, _, err = c.Get(context.TODO(),
                                WithLabels(map[string]string{"service": 
"client"}),
                                WithGetProject("client_test"),
                                WithWait("10s"))
@@ -80,8 +88,8 @@ func TestClient_Put(t *testing.T) {
                }
                _, err := c.Put(context.TODO(), kv, WithProject("client_test"))
                assert.NoError(t, err)
-               t.Log(c.CurrentRevision)
-               kvs, err = c.Get(context.TODO(),
+               t.Log(c.CurrentRevision())
+               kvs, _, err = c.Get(context.TODO(),
                        WithGetProject("client_test"),
                        WithLabels(map[string]string{"service": "client"}),
                        WithExact())
@@ -103,7 +111,7 @@ func TestClient_Delete(t *testing.T) {
        kvBody.Labels["env"] = "client_test"
        kv, err := c.Put(context.TODO(), kvBody, WithProject("client_test"))
        assert.NoError(t, err)
-       kvs, err := c.Get(context.TODO(),
+       kvs, _, err := c.Get(context.TODO(),
                WithKey("time"),
                WithGetProject("client_test"),
                WithLabels(map[string]string{"env": "client_test"}))
diff --git a/client/options.go b/client/options.go
index 6b2b9a7..f450e33 100644
--- a/client/options.go
+++ b/client/options.go
@@ -17,6 +17,8 @@
 
 package client
 
+import "strconv"
+
 const (
        defaultProject = "default"
 )
@@ -29,11 +31,12 @@ type OpOption func(*OpOptions)
 
 //GetOptions is the options of client func
 type GetOptions struct {
-       Labels  []map[string]string
-       Project string
-       Key     string
-       Wait    string
-       Exact   bool
+       Labels   []map[string]string
+       Project  string
+       Key      string
+       Wait     string
+       Exact    bool
+       Revision string
 }
 
 //OpOptions is the options of client func
@@ -78,6 +81,13 @@ func WithKey(k string) GetOption {
        }
 }
 
+//WithRevision query keys with certain revision
+func WithRevision(revision int) GetOption {
+       return func(options *GetOptions) {
+               options.Revision = strconv.Itoa(revision)
+       }
+}
+
 //WithProject set project to param
 func WithProject(project string) OpOption {
        return func(options *OpOptions) {

Reply via email to