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 19f1abd  #84 event support exact match (#86)
19f1abd is described below

commit 19f1abdb77b4796f9186b6f2087ed64b22baf023
Author: GuoYL <[email protected]>
AuthorDate: Tue Feb 11 09:21:26 2020 +0800

    #84 event support exact match (#86)
    
    * event support exact match
    
    * test CI
    
    * add unit test
    
    * test CI
    
    * import exist const
---
 pkg/common/common.go                   | 16 +++++++++++++
 server/pubsub/struct.go                |  8 +++++++
 server/resource/v1/common.go           | 24 +++++--------------
 server/resource/v1/kv_resource.go      | 28 ++++++++++++----------
 server/resource/v1/kv_resource_test.go | 44 +++++++++++++++++++++++++++++++++-
 server/resource/v1/label_resouce.go    |  2 +-
 6 files changed, 89 insertions(+), 33 deletions(-)

diff --git a/pkg/common/common.go b/pkg/common/common.go
index 41bd161..7d5a4e1 100644
--- a/pkg/common/common.go
+++ b/pkg/common/common.go
@@ -17,6 +17,8 @@
 
 package common
 
+import "time"
+
 //match mode
 const (
        QueryParamQ      = "q"
@@ -43,3 +45,17 @@ const (
        ContentTypeJSON = "application/json"
        ContentTypeYaml = "text/yaml"
 )
+
+//const for server/resource/v1
+const (
+       PatternExact            = "exact"
+       MsgDomainMustNotBeEmpty = "domain must not be empty"
+       MsgIllegalLabels        = "label value can not be empty, " +
+               "label can not be duplicated, please check query parameters"
+       MsgIllegalDepth     = "X-Depth must be number"
+       MsgInvalidWait      = "wait param should be formed with number and time 
unit like 5s,100ms, and less than 5m"
+       MsgInvalidRev       = "revision param should be formed with number 
greater than 0"
+       ErrKvIDMustNotEmpty = "must supply kv id if you want to remove key"
+
+       MaxWait = 5 * time.Minute
+)
diff --git a/server/pubsub/struct.go b/server/pubsub/struct.go
index 3c56ba5..1e8cdae 100644
--- a/server/pubsub/struct.go
+++ b/server/pubsub/struct.go
@@ -20,6 +20,8 @@ package pubsub
 import (
        "encoding/json"
        "errors"
+       "github.com/apache/servicecomb-kie/pkg/common"
+       "reflect"
        "strings"
 )
 
@@ -46,6 +48,7 @@ type Topic struct {
        LabelsFormat string            `json:"labels,omitempty"`
        DomainID     string            `json:"domainID,omitempty"`
        Project      string            `json:"project,omitempty"`
+       MatchType    string            `json:"match,omitempty"`
 }
 
 //ParseTopicString parse topic string to topic struct
@@ -78,6 +81,11 @@ func (t *Topic) Match(event *KVChangeEvent) bool {
                        match = true
                }
        }
+       if t.MatchType == common.PatternExact {
+               if !reflect.DeepEqual(t.Labels, event.Labels) {
+                       return false
+               }
+       }
        for k, v := range t.Labels {
                if event.Labels[k] != v {
                        return false
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index 3414554..730d233 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -37,22 +37,10 @@ import (
 )
 
 //const of server
-const (
-       PatternExact            = "exact"
-       MsgDomainMustNotBeEmpty = "domain must not be empty"
-       MsgIllegalLabels        = "label value can not be empty, " +
-               "label can not be duplicated, please check query parameters"
-       MsgIllegalDepth     = "X-Depth must be number"
-       MsgInvalidWait      = "wait param should be formed with number and time 
unit like 5s,100ms, and less than 5m"
-       MsgInvalidRev       = "revision param should be formed with number 
greater than 0"
-       ErrKvIDMustNotEmpty = "must supply kv id if you want to remove key"
-
-       MaxWait = 5 * time.Minute
-)
 
 //err
 var (
-       ErrInvalidRev = errors.New(MsgInvalidRev)
+       ErrInvalidRev = errors.New(common.MsgInvalidRev)
 )
 
 //ReadDomain get domain info from attribute
@@ -141,7 +129,7 @@ func getLabels(rctx *restful.Context) (map[string]string, 
error) {
        for _, v := range labelSlice {
                v := strings.Split(v, ":")
                if len(v) != 2 {
-                       return nil, errors.New(MsgIllegalLabels)
+                       return nil, errors.New(common.MsgIllegalLabels)
                }
                labels[v[0]] = v[1]
        }
@@ -163,15 +151,15 @@ func isRevised(ctx context.Context, revStr, domain 
string) (bool, error) {
 }
 func getMatchPattern(rctx *restful.Context) string {
        m := rctx.ReadQueryParameter(common.QueryParamMatch)
-       if m != "" && m != PatternExact {
+       if m != "" && m != common.PatternExact {
                return ""
        }
        return m
 }
 func eventHappened(rctx *restful.Context, waitStr string, topic *pubsub.Topic) 
(bool, error) {
        d, err := time.ParseDuration(waitStr)
-       if err != nil || d > MaxWait {
-               return false, errors.New(MsgInvalidWait)
+       if err != nil || d > common.MaxWait {
+               return false, errors.New(common.MsgInvalidWait)
        }
        happened := true
        o := &pubsub.Observer{
@@ -221,7 +209,7 @@ func queryAndResponse(rctx *restful.Context,
                service.WithLimit(limit),
                service.WithOffset(offset),
        }
-       if m == PatternExact {
+       if m == common.PatternExact {
                opts = append(opts, service.WithExactLabels())
        }
        kv, err := service.KVService.List(rctx.Ctx, domain.(string), project, 
opts...)
diff --git a/server/resource/v1/kv_resource.go 
b/server/resource/v1/kv_resource.go
index 87ba64b..7c7872a 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -46,7 +46,7 @@ func (r *KVResource) Put(context *restful.Context) {
        }
        domain := ReadDomain(context)
        if domain == nil {
-               WriteErrResponse(context, http.StatusInternalServerError, 
MsgDomainMustNotBeEmpty, common.ContentTypeText)
+               WriteErrResponse(context, http.StatusInternalServerError, 
common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
                return
        }
        kv.Key = key
@@ -88,12 +88,12 @@ func (r *KVResource) GetByKey(rctx *restful.Context) {
        project := rctx.ReadPathParameter("project")
        labels, err := getLabels(rctx)
        if err != nil {
-               WriteErrResponse(rctx, http.StatusBadRequest, MsgIllegalLabels, 
common.ContentTypeText)
+               WriteErrResponse(rctx, http.StatusBadRequest, 
common.MsgIllegalLabels, common.ContentTypeText)
                return
        }
        domain := ReadDomain(rctx)
        if domain == nil {
-               WriteErrResponse(rctx, http.StatusInternalServerError, 
MsgDomainMustNotBeEmpty, common.ContentTypeText)
+               WriteErrResponse(rctx, http.StatusInternalServerError, 
common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
                return
        }
        limitStr := rctx.ReadQueryParameter("limit")
@@ -112,7 +112,7 @@ func (r *KVResource) List(rctx *restful.Context) {
        project := rctx.ReadPathParameter("project")
        domain := ReadDomain(rctx)
        if domain == nil {
-               WriteErrResponse(rctx, http.StatusInternalServerError, 
MsgDomainMustNotBeEmpty, common.ContentTypeText)
+               WriteErrResponse(rctx, http.StatusInternalServerError, 
common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
                return
        }
        labels, err := getLabels(rctx)
@@ -139,9 +139,10 @@ func returnData(rctx *restful.Context, domain interface{}, 
project string, label
                        return
                }
                changed, err := eventHappened(rctx, wait, &pubsub.Topic{
-                       Labels:   labels,
-                       Project:  project,
-                       DomainID: domain.(string),
+                       Labels:    labels,
+                       Project:   project,
+                       MatchType: getMatchPattern(rctx),
+                       DomainID:  domain.(string),
                })
                if err != nil {
                        WriteErrResponse(rctx, http.StatusBadRequest, 
err.Error(), common.ContentTypeText)
@@ -167,9 +168,10 @@ func returnData(rctx *restful.Context, domain interface{}, 
project string, label
                        return
                } else if wait != "" {
                        changed, err := eventHappened(rctx, wait, &pubsub.Topic{
-                               Labels:   labels,
-                               Project:  project,
-                               DomainID: domain.(string),
+                               Labels:    labels,
+                               Project:   project,
+                               MatchType: getMatchPattern(rctx),
+                               DomainID:  domain.(string),
                        })
                        if err != nil {
                                WriteErrResponse(rctx, http.StatusBadRequest, 
err.Error(), common.ContentTypeText)
@@ -198,7 +200,7 @@ func (r *KVResource) Search(context *restful.Context) {
        project := context.ReadPathParameter("project")
        domain := ReadDomain(context)
        if domain == nil {
-               WriteErrResponse(context, http.StatusInternalServerError, 
MsgDomainMustNotBeEmpty, common.ContentTypeText)
+               WriteErrResponse(context, http.StatusInternalServerError, 
common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
                return
        }
        var kvs []*model.KVResponse
@@ -261,12 +263,12 @@ func (r *KVResource) Delete(context *restful.Context) {
        project := context.ReadPathParameter("project")
        domain := ReadDomain(context)
        if domain == nil {
-               WriteErrResponse(context, http.StatusInternalServerError, 
MsgDomainMustNotBeEmpty, common.ContentTypeText)
+               WriteErrResponse(context, http.StatusInternalServerError, 
common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
                return
        }
        kvID := context.ReadQueryParameter(common.QueryParamKeyID)
        if kvID == "" {
-               WriteErrResponse(context, http.StatusBadRequest, 
ErrKvIDMustNotEmpty, common.ContentTypeText)
+               WriteErrResponse(context, http.StatusBadRequest, 
common.ErrKvIDMustNotEmpty, common.ContentTypeText)
                return
        }
        err := service.KVService.Delete(context.Ctx, kvID, domain.(string), 
project)
diff --git a/server/resource/v1/kv_resource_test.go 
b/server/resource/v1/kv_resource_test.go
index a60bb30..7765464 100644
--- a/server/resource/v1/kv_resource_test.go
+++ b/server/resource/v1/kv_resource_test.go
@@ -36,6 +36,7 @@ import (
        "io/ioutil"
        "net/http"
        "net/http/httptest"
+       "sync"
        "testing"
        "time"
 
@@ -206,7 +207,7 @@ func TestKVResource_List(t *testing.T) {
                t.Log(duration)
                assert.Equal(t, http.StatusNotModified, 
resp.Result().StatusCode)
        })
-       t.Run("list kv by service label, with wait param,will too 1s and return 
304", func(t *testing.T) {
+       t.Run("list kv by service label, with wait param,will exceed 1s and 
return 304", func(t *testing.T) {
                r, _ := http.NewRequest("GET", 
"/v1/test/kie/kv?label=service:utService&wait=1s", nil)
                noopH := &handler2.NoopAuthHandler{}
                chain, _ := handler.CreateChain(common.Provider, "testchain1", 
noopH.Name())
@@ -254,6 +255,47 @@ func TestKVResource_List(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, 1, len(result.Data))
        })
+       t.Run("list kv by service label, with wait and match param,not exact 
match and return 304", func(t *testing.T) {
+               r, _ := http.NewRequest("GET", 
"/v1/test/kie/kv?label=match:test&wait=10s&match=exact", nil)
+               noopH := &handler2.NoopAuthHandler{}
+               chain, _ := handler.CreateChain(common.Provider, 
"testchain-match", noopH.Name())
+               r.Header.Set("Content-Type", "application/json")
+               kvr := &v1.KVResource{}
+               c, err := restfultest.New(kvr, chain)
+               assert.NoError(t, err)
+               resp := httptest.NewRecorder()
+               var wg sync.WaitGroup
+               wg.Add(1)
+               go func() {
+                       kv := &model.KVDoc{
+                               Value:  "val",
+                               Labels: map[string]string{"dummy": "test", 
"match": "test"},
+                       }
+                       j, _ := json.Marshal(kv)
+                       r2, _ := http.NewRequest("PUT", 
"/v1/test/kie/kv/testKey", bytes.NewBuffer(j))
+                       noopH2 := &handler2.NoopAuthHandler{}
+                       chain2, _ := handler.CreateChain(common.Provider, 
"testchain-match", noopH2.Name())
+                       r2.Header.Set("Content-Type", "application/json")
+                       kvr2 := &v1.KVResource{}
+                       c2, _ := restfultest.New(kvr2, chain2)
+                       resp2 := httptest.NewRecorder()
+                       c2.ServeHTTP(resp2, r2)
+                       body, _ := ioutil.ReadAll(resp2.Body)
+                       data := &model.KVDoc{}
+                       err = json.Unmarshal(body, data)
+                       assert.NotEmpty(t, data.ID)
+                       wg.Done()
+               }()
+               start := time.Now()
+               c.ServeHTTP(resp, r)
+               wg.Wait()
+               duration := time.Since(start)
+               body, _ := ioutil.ReadAll(resp.Body)
+               data := &model.KVDoc{}
+               err = json.Unmarshal(body, data)
+               assert.Equal(t, 304, resp.Code)
+               t.Log(duration)
+       })
 }
 func TestKVResource_GetByKey(t *testing.T) {
        t.Run("get one key by label, exact match,should return 1 kv", func(t 
*testing.T) {
diff --git a/server/resource/v1/label_resouce.go 
b/server/resource/v1/label_resouce.go
index c573189..49e42f7 100644
--- a/server/resource/v1/label_resouce.go
+++ b/server/resource/v1/label_resouce.go
@@ -26,7 +26,7 @@ func (r *LabelResource) PutLabel(context *restful.Context) {
        entity.Project = context.ReadPathParameter("project")
        domain := ReadDomain(context)
        if domain == nil {
-               WriteErrResponse(context, http.StatusInternalServerError, 
MsgDomainMustNotBeEmpty, common.ContentTypeText)
+               WriteErrResponse(context, http.StatusInternalServerError, 
common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
                return
        }
        entity.Domain = domain.(string)

Reply via email to