This is an automated email from the ASF dual-hosted git repository.
littlecui 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 93bbb89 add value filter in ListKV API (#302)
93bbb89 is described below
commit 93bbb89069fe7b4dd017422e897246837dc665c1
Author: little-cui <[email protected]>
AuthorDate: Fri Nov 24 09:00:47 2023 +0800
add value filter in ListKV API (#302)
Co-authored-by: tornado-ssy <[email protected]>
---
pkg/common/common.go | 1 +
pkg/model/db_schema.go | 1 +
server/datasource/etcd/kv/kv_cache.go | 11 +++++++----
server/datasource/etcd/kv/kv_dao.go | 10 +++++-----
server/datasource/mongo/kv/kv_dao.go | 3 +++
server/datasource/options.go | 8 ++++++++
server/resource/v1/kv_resource.go | 1 +
server/resource/v1/kv_resource_test.go | 32 ++++++++++++++++++++++++++++++++
server/service/kv/kv_svc.go | 5 +++++
9 files changed, 63 insertions(+), 9 deletions(-)
diff --git a/pkg/common/common.go b/pkg/common/common.go
index 5188d32..9e452f3 100644
--- a/pkg/common/common.go
+++ b/pkg/common/common.go
@@ -27,6 +27,7 @@ const (
QueryParamRev = "revision"
QueryParamMatch = "match"
QueryParamKey = "key"
+ QueryParamValue = "value"
QueryParamLabel = "label"
QueryParamStatus = "status"
QueryParamOffset = "offset"
diff --git a/pkg/model/db_schema.go b/pkg/model/db_schema.go
index 28b98d3..442da43 100644
--- a/pkg/model/db_schema.go
+++ b/pkg/model/db_schema.go
@@ -96,6 +96,7 @@ type ListKVRequest struct {
Project string `json:"project,omitempty"
yaml:"project,omitempty" validate:"min=1,max=256,commonName"`
Domain string `json:"domain,omitempty"
yaml:"domain,omitempty" validate:"min=1,max=256,commonName"` //redundant
Key string `json:"key" yaml:"key"
validate:"max=128,getKey"`
+ Value string `json:"value" yaml:"value" validate:"max=128"`
Labels map[string]string `json:"labels,omitempty"
yaml:"labels,omitempty" validate:"max=8,dive,keys,labelK,endkeys,labelV"`
//redundant
Offset int64 `validate:"min=0"`
Limit int64 `validate:"min=0,max=100"`
diff --git a/server/datasource/etcd/kv/kv_cache.go
b/server/datasource/etcd/kv/kv_cache.go
index 5776bf7..61d017b 100644
--- a/server/datasource/etcd/kv/kv_cache.go
+++ b/server/datasource/etcd/kv/kv_cache.go
@@ -220,9 +220,9 @@ func (kc *Cache) DeleteKvDoc(kvID string) {
kc.kvDocCache.Delete(kvID)
}
-func Search(ctx context.Context, req *CacheSearchReq) (*model.KVResponse,
bool, error) {
+func Search(ctx context.Context, req *CacheSearchReq) (*model.KVResponse,
bool) {
if !req.Opts.ExactLabels {
- return nil, false, nil
+ return nil, false
}
openlog.Debug(fmt.Sprintf("using cache to search kv, domain %v, project
%v, opts %+v", req.Domain, req.Project, *req.Opts))
@@ -233,7 +233,7 @@ func Search(ctx context.Context, req *CacheSearchReq)
(*model.KVResponse, bool,
kvIds, ok := kvCache.LoadKvIDSet(cacheKey)
if !ok {
kvCache.StoreKvIDSet(cacheKey, IDSet{})
- return result, true, nil
+ return result, true
}
var docs []*model.KVDoc
@@ -257,7 +257,7 @@ func Search(ctx context.Context, req *CacheSearchReq)
(*model.KVResponse, bool,
}
}
result.Total = len(result.Data)
- return result, true, nil
+ return result, true
}
func (kc *Cache) getKvFromEtcd(ctx context.Context, req *CacheSearchReq,
kvIdsLeft []string) []*model.KVDoc {
@@ -304,6 +304,9 @@ func isMatch(req *CacheSearchReq, doc *model.KVDoc) bool {
if req.Regex != nil && !req.Regex.MatchString(doc.Key) {
return false
}
+ if req.Opts.Value != "" && !strings.Contains(doc.Value, req.Opts.Value)
{
+ return false
+ }
return true
}
diff --git a/server/datasource/etcd/kv/kv_dao.go
b/server/datasource/etcd/kv/kv_dao.go
index 84c6958..2332b58 100644
--- a/server/datasource/etcd/kv/kv_dao.go
+++ b/server/datasource/etcd/kv/kv_dao.go
@@ -524,18 +524,15 @@ func (s *Dao) listData(ctx context.Context, project,
domain string, options ...d
}
if Enabled() {
- result, useCache, err := Search(ctx, &CacheSearchReq{
+ result, useCache := Search(ctx, &CacheSearchReq{
Domain: domain,
Project: project,
Opts: &opts,
Regex: regex,
})
- if useCache && err == nil {
+ if useCache {
return result, opts, nil
}
- if useCache && err != nil {
- openlog.Error("using cache to search kv failed: " +
err.Error())
- }
}
result, err := matchLabelsSearch(ctx, domain, project, regex, opts)
@@ -646,5 +643,8 @@ func filterMatch(doc *model.KVDoc, opts
datasource.FindOptions, regex *regexp.Re
if opts.LabelFormat != "" && doc.LabelFormat != opts.LabelFormat {
return false
}
+ if opts.Value != "" && !strings.Contains(doc.Value, opts.Value) {
+ return false
+ }
return true
}
diff --git a/server/datasource/mongo/kv/kv_dao.go
b/server/datasource/mongo/kv/kv_dao.go
index 79eb6ff..79ed45f 100644
--- a/server/datasource/mongo/kv/kv_dao.go
+++ b/server/datasource/mongo/kv/kv_dao.go
@@ -271,6 +271,9 @@ func findKV(ctx context.Context, domain string, project
string, opts datasource.
filter["key"] = bson.M{"$regex": "^" + value + "$",
"$options": "$i"}
}
}
+ if opts.Value != "" {
+ filter["value"] = bson.M{"$regex": opts.Value}
+ }
if len(opts.Labels) != 0 {
for k, v := range opts.Labels {
filter["labels."+k] = v
diff --git a/server/datasource/options.go b/server/datasource/options.go
index 2e311f5..7de8877 100644
--- a/server/datasource/options.go
+++ b/server/datasource/options.go
@@ -63,6 +63,7 @@ type FindOptions struct {
Depth int
ID string
Key string
+ Value string
Labels map[string]string
LabelFormat string
ClearLabel bool
@@ -115,6 +116,13 @@ func WithKey(key string) FindOption {
}
}
+// WithValue find by value
+func WithValue(value string) FindOption {
+ return func(o *FindOptions) {
+ o.Value = value
+ }
+}
+
// WithStatus enabled/disabled
func WithStatus(status string) FindOption {
return func(o *FindOptions) {
diff --git a/server/resource/v1/kv_resource.go
b/server/resource/v1/kv_resource.go
index 0f259d2..5a163fb 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -175,6 +175,7 @@ func (r *KVResource) List(rctx *restful.Context) {
Project: rctx.ReadPathParameter(common.PathParameterProject),
Domain: ReadDomain(rctx.Ctx),
Key: rctx.ReadQueryParameter(common.QueryParamKey),
+ Value: rctx.ReadQueryParameter(common.QueryParamValue),
Status: rctx.ReadQueryParameter(common.QueryParamStatus),
Match: getMatchPattern(rctx),
}
diff --git a/server/resource/v1/kv_resource_test.go
b/server/resource/v1/kv_resource_test.go
index cf25747..c52c3aa 100644
--- a/server/resource/v1/kv_resource_test.go
+++ b/server/resource/v1/kv_resource_test.go
@@ -253,6 +253,38 @@ func TestKVResource_List(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 3, len(result.Data))
})
+ t.Run("list kv by value, should return 1 kv", func(t *testing.T) {
+ r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?value=aaa",
nil)
+ r.Header.Set("Content-Type", "application/json")
+ kvr := &v1.KVResource{}
+ c, err := restfultest.New(kvr, nil)
+ assert.NoError(t, err)
+ resp := httptest.NewRecorder()
+ c.ServeHTTP(resp, r)
+ body, err := ioutil.ReadAll(resp.Body)
+ assert.NoError(t, err)
+ assert.Equal(t, http.StatusOK, resp.Code, string(body))
+ result := &model.KVResponse{}
+ err = json.Unmarshal(body, result)
+ assert.NoError(t, err)
+ assert.Equal(t, 1, len(result.Data))
+ })
+ t.Run("list kv by value, should return 1 kv", func(t *testing.T) {
+ r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?value=AAA",
nil)
+ r.Header.Set("Content-Type", "application/json")
+ kvr := &v1.KVResource{}
+ c, err := restfultest.New(kvr, nil)
+ assert.NoError(t, err)
+ resp := httptest.NewRecorder()
+ c.ServeHTTP(resp, r)
+ body, err := ioutil.ReadAll(resp.Body)
+ assert.NoError(t, err)
+ assert.Equal(t, http.StatusOK, resp.Code, string(body))
+ result := &model.KVResponse{}
+ err = json.Unmarshal(body, result)
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(result.Data))
+ })
var rev string
t.Run("list kv by service label, exact match,should return 2 kv",
func(t *testing.T) {
r, _ := http.NewRequest("GET",
"/v1/kv_test/kie/kv?label=service:utService&match=exact", nil)
diff --git a/server/service/kv/kv_svc.go b/server/service/kv/kv_svc.go
index acac1da..f5e81c5 100644
--- a/server/service/kv/kv_svc.go
+++ b/server/service/kv/kv_svc.go
@@ -20,6 +20,7 @@ package kv
import (
"context"
"crypto/sha256"
+ "errors"
"fmt"
"strings"
"time"
@@ -45,6 +46,7 @@ var listSema =
concurrency.NewSemaphore(concurrency.DefaultConcurrency)
func ListKV(ctx context.Context, request *model.ListKVRequest) (int64,
*model.KVResponse, *errsvc.Error) {
opts := []datasource.FindOption{
datasource.WithKey(request.Key),
+ datasource.WithValue(request.Value),
datasource.WithLabels(request.Labels),
datasource.WithOffset(request.Offset),
datasource.WithLimit(request.Limit),
@@ -126,6 +128,9 @@ func Create(ctx context.Context, kv *model.KVDoc)
(*model.KVDoc, *errsvc.Error)
kv, err = datasource.GetBroker().GetKVDao().Create(ctx, kv,
datasource.WithSync(sync.FromContext(ctx)))
if err != nil {
openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
+ if errors.Is(err, datasource.ErrKVAlreadyExists) {
+ err = config.NewError(config.ErrRecordAlreadyExists,
datasource.ErrKVAlreadyExists.Error())
+ }
return nil, util.SvcErr(err)
}
err = datasource.GetBroker().GetHistoryDao().AddHistory(ctx, kv)