You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by as...@apache.org on 2019/06/27 11:53:23 UTC

[servicecomb-kie] 12/29: add delete by id string

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

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

commit 49d238a4c3977fbf897fccdcdbfafa62bc9b1282
Author: wangqijun <wa...@sohu.com>
AuthorDate: Fri May 24 22:18:57 2019 +0800

    add delete by id string
---
 server/dao/kv.go                  |  7 +++--
 server/dao/kv_test.go             | 53 ++++++++++++++++++++++++++++++++++++
 server/dao/mongodb.go             | 38 +++++++++++++++++++++++++-
 server/resource/v1/common.go      |  5 +++-
 server/resource/v1/kv_resource.go | 57 ++++++++++++++++++++++++++++++++++++++-
 5 files changed, 153 insertions(+), 7 deletions(-)

diff --git a/server/dao/kv.go b/server/dao/kv.go
index de32cc3..9cf40fe 100644
--- a/server/dao/kv.go
+++ b/server/dao/kv.go
@@ -21,9 +21,9 @@ package dao
 import (
 	"crypto/tls"
 	"errors"
-	"time"
-	"github.com/apache/servicecomb-kie/server/config"
 	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/apache/servicecomb-kie/server/config"
+	"time"
 )
 
 var ErrMissingDomain = errors.New("domain info missing, illegal access")
@@ -35,8 +35,7 @@ type KV interface {
 	CreateOrUpdate(kv *model.KV) (*model.KV, error)
 	//do not use primitive.ObjectID as return to decouple with mongodb, we can afford perf lost
 	Exist(key, domain string, labels model.Labels) (string, error)
-	DeleteByID(id string) error
-	Delete(key, domain string, labels model.Labels) error
+	Delete(ids []string, domain string) error
 	Find(domain string, options ...FindOption) ([]*model.KV, error)
 	AddHistory(kv *model.KV) error
 	//RollBack(kv *KV, version string) error
diff --git a/server/dao/kv_test.go b/server/dao/kv_test.go
index 9cb23ad..81bd106 100644
--- a/server/dao/kv_test.go
+++ b/server/dao/kv_test.go
@@ -189,4 +189,57 @@ var _ = Describe("Kv mongodb service", func() {
 
 		})
 	})
+
+	Describe("delete key", func() {
+		Context("delete key by id,seperated by ',' ", func() {
+			kv1, err := s.CreateOrUpdate(&model.KV{
+				Key:    "timeout",
+				Value:  "20s",
+				Domain: "default",
+				Labels: map[string]string{
+					"env": "test",
+				},
+			})
+			It("should not return err", func() {
+				Expect(err).Should(BeNil())
+			})
+
+			kv2, err := s.CreateOrUpdate(&model.KV{
+				Key:    "times",
+				Value:  "3",
+				Domain: "default",
+				Labels: map[string]string{
+					"env": "test",
+				},
+			})
+			It("should not return err", func() {
+				Expect(err).Should(BeNil())
+			})
+
+			ids := []string{kv1.ID.Hex(), kv2.ID.Hex()}
+			err = s.Delete(ids, "default")
+			It("should not return err", func() {
+				Expect(err).Should(BeNil())
+			})
+
+		})
+		Context("test miss ids, no panic", func() {
+			err := s.Delete(nil, "default")
+			It("should not return err", func() {
+				Expect(err).Should(BeNil())
+			})
+		})
+		Context("Test encode error ", func() {
+			err := s.Delete([]string{"12312312321"}, "default")
+			It("should return err", func() {
+				Expect(err).To(HaveOccurred())
+			})
+		})
+		Context("Test miss domain error ", func() {
+			err := s.Delete([]string{"5ce3602381fc6e33708b9621"}, "")
+			It("should return err", func() {
+				Expect(err).Should(Equal(dao.ErrMissingDomain))
+			})
+		})
+	})
 })
diff --git a/server/dao/mongodb.go b/server/dao/mongodb.go
index cbaabad..9fc6ad0 100644
--- a/server/dao/mongodb.go
+++ b/server/dao/mongodb.go
@@ -224,7 +224,43 @@ func (s *MongodbService) DeleteByID(id string) error {
 	return nil
 }
 
-func (s *MongodbService) Delete(key, domain string, labels model.Labels) error {
+func (s *MongodbService) Delete(ids []string, domain string) error {
+	if len(ids) == 0 {
+		openlogging.Warn("delete error,ids is blank")
+		return nil
+	}
+	if domain == "" {
+		return ErrMissingDomain
+	}
+	collection := s.c.Database(DB).Collection(CollectionKV)
+	//transfer id
+	var oid []primitive.ObjectID
+	for _, v := range ids {
+		if v == "" {
+			openlogging.Warn("ids contains continuous ','")
+			continue
+		}
+		hex, err := primitive.ObjectIDFromHex(v)
+		if err != nil {
+			openlogging.Error(fmt.Sprintf("convert %s ,err:%s", v, err))
+			return err
+		}
+		oid = append(oid, hex)
+	}
+	//use in filter
+	filter := &bson.M{"_id": &bson.M{"$in": oid}, "domain": domain}
+	ctx, _ := context.WithTimeout(context.Background(), DefaultTimeout)
+	dr, err := collection.DeleteMany(ctx, filter)
+	//check error and delete number
+	if err != nil {
+		openlogging.Error(fmt.Sprintf("delete [%s] failed : [%s]", filter, err))
+		return err
+	}
+	if dr.DeletedCount != int64(len(oid)) {
+		openlogging.Warn(fmt.Sprintf(" The actual number of deletions[%d] is not equal to the parameters[%d].", dr.DeletedCount, len(oid)))
+	} else {
+		openlogging.Info(fmt.Sprintf("delete success,count=%d", dr.DeletedCount))
+	}
 	return nil
 }
 func (s *MongodbService) AddHistory(kv *model.KV) error {
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index bee9f36..e246602 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -27,10 +27,13 @@ import (
 )
 
 const (
+	FindExact               = "exact"
+	FindMany                = "greedy"
 	MsgDomainMustNotBeEmpty = "domain must not be empty"
-	MsgIllegalFindPolicy    = "value of header "+common.HeaderMatch+" can be greedy or exact"
+	MsgIllegalFindPolicy    = "value of header " + common.HeaderMatch + " can be greedy or exact"
 	MsgIllegalLabels        = "label's value can not be empty, " +
 		"label can not be duplicated, please check your query parameters"
+	ErrIDMustNotEmpty = "must supply id if you want to remove key"
 )
 
 func ReadDomain(context *restful.Context) interface{} {
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index 0030e7b..4839279 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -20,6 +20,7 @@ package v1
 
 import (
 	"encoding/json"
+	"fmt"
 	"github.com/apache/servicecomb-kie/pkg/common"
 	"github.com/apache/servicecomb-kie/pkg/model"
 	"github.com/apache/servicecomb-kie/server/dao"
@@ -27,6 +28,7 @@ import (
 	"github.com/go-chassis/go-chassis/server/restful"
 	"github.com/go-mesh/openlogging"
 	"net/http"
+	"strings"
 )
 
 type KVResource struct {
@@ -159,7 +161,28 @@ func (r *KVResource) FindByLabels(context *restful.Context) {
 
 }
 func (r *KVResource) Delete(context *restful.Context) {
-
+	domain := ReadDomain(context)
+	if domain == nil {
+		WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty)
+	}
+	ids := context.ReadPathParameter("ids")
+	if ids == "" {
+		WriteErrResponse(context, http.StatusBadRequest, ErrIDMustNotEmpty)
+		return
+	}
+	idArray := strings.Split(ids, ",")
+	s, err := dao.NewKVService()
+	if err != nil {
+		WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+		return
+	}
+	err = s.Delete(idArray, domain.(string))
+	if err != nil {
+		openlogging.Error(fmt.Sprintf("delete ids=%s,err=%s", ids, err.Error()))
+		WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+		return
+	}
+	context.WriteHeader(http.StatusNoContent)
 }
 
 //URLPatterns defined config operations
@@ -253,6 +276,38 @@ func (r *KVResource) URLPatterns() []restful.Route {
 			},
 			Consumes: []string{"application/json"},
 			Produces: []string{"application/json"},
+		}, {
+			Method:           http.MethodDelete,
+			Path:             "/v1/kv/{ids}",
+			ResourceFuncName: "Delete",
+			FuncDesc:         "delete key by id,seperated by ','",
+			Parameters: []*restful.Parameters{
+				{
+					DataType:  "string",
+					Name:      "X-Domain-Name",
+					ParamType: goRestful.HeaderParameterKind,
+				}, {
+					DataType:  "string",
+					Name:      "ids",
+					ParamType: goRestful.PathParameterKind,
+					Desc: "The id strings to be removed are separated by ',',If the actual number of deletions " +
+						"and the number of parameters are not equal, no error will be returned and only warn log will be printed.",
+				},
+			},
+			Returns: []*restful.Returns{
+				{
+					Code:    http.StatusNoContent,
+					Message: "Delete success",
+				},
+				{
+					Code:    http.StatusBadRequest,
+					Message: "Failed,check url",
+				},
+				{
+					Code:    http.StatusInternalServerError,
+					Message: "Server error",
+				},
+			},
 		},
 	}
 }