You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2020/02/11 01:21:35 UTC
[servicecomb-kie] branch master updated: #84 event support exact
match (#86)
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 <53...@users.noreply.github.com>
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)