You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by GitBox <gi...@apache.org> on 2021/06/15 04:00:25 UTC

[GitHub] [servicecomb-kie] Sphairis opened a new pull request #185: add upload interface

Sphairis opened a new pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661924291



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,129 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	strategy := service.GetType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, executeErr := strategy.Execute(kv, rctx, isDuplicate)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] aseTo2016 commented on a change in pull request #185: [wip]add upload interface

Posted by GitBox <gi...@apache.org>.
aseTo2016 commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r656916592



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,51 +41,133 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	logicOfOverride(kvs, rctx, result)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs *[]*model.KVDoc, rctx *restful.Context, result *model.DocRespOfUpload) {

Review comment:
       建议kvs使用slice,通过kvs[:]传入即可,result *model.DocRespOfUpload作为返回参数




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661543838



##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))

Review comment:
       done

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+	t.Run("test force with the same key and not the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))

Review comment:
       done

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661440951



##########
File path: server/resource/v1/override_strategy.go
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/go-chassis/v2/server/restful"
+)
+
+var overrideMap = make(map[string]strategyOverride)
+
+func init() {
+	Register()
+}
+
+type OverrideType struct {
+}
+
+type strategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, errsvc.Error)
+}
+
+func Register() {
+	overrideMap["force"] = &Force{}
+	overrideMap["abort"] = &Abort{}
+	overrideMap["skip"] = &Skip{}

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: [wip]add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r654761433



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(overridden, common.Stop) && stopped {
+			openlog.Info(fmt.Sprintf("stop create kv %s", kv.Key))
+			getFailedKV(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		domain := ReadDomain(rctx.Ctx)
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err = validator.Validate(kv)
+		if err != nil {
+			getFailedKV(config.ErrInvalidParams, err.Error(), key, result)
+			continue
+		}
+		err = quota.PreCreate("", kv.Domain, "", 1)
+		if err != nil {
+			if err == quota.ErrReached {
+				openlog.Info(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
+				getFailedKV(config.ErrNotEnoughQuota, err.Error(), key, result)
+				continue
+			}
+			openlog.Error(err.Error())
+			getFailedKV(config.ErrInternal, "quota check failed", key, result)
+			continue
+		}
+		var kvOld *model.KVDoc
+		kvOld, err = service.KVService.Create(rctx.Ctx, kv)
+		kv.ID = kvOld.ID
+		if err != nil {
+			openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
+			if err == session.ErrKVAlreadyExists {
+				if strings.EqualFold(overridden, common.Skip) {
+					openlog.Info(fmt.Sprintf("skip create kv %s", kv.Key))
+					getFailedKV(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", key, result)
+				} else if strings.EqualFold(overridden, common.Force) {
+					kvReq := new(model.UpdateKVRequest)
+					kvReq.ID = kv.ID
+					kvReq.Value = kv.Value
+					kvReq.Domain = domain
+					kvReq.Project = project
+					kvReq.Status = kv.Status
+					kv, err = service.KVService.Update(rctx.Ctx, kvReq)
+					result.Success = append(result.Success, kv)
+				} else {
+					getFailedKV(config.ErrRecordAlreadyExists, err.Error(), key, result)
+				}
+				stopped = true
+				continue
+			}
+			getFailedKV(config.ErrInternal, "create kv failed", key, result)
+			continue
+		}
+		err = pubsub.Publish(&pubsub.KVChangeEvent{
+			Key:      kv.Key,
+			Labels:   kv.Labels,
+			Project:  project,
+			DomainID: kv.Domain,
+			Action:   pubsub.ActionPut,
+		})
+		if err != nil {
+			openlog.Warn("lost kv change event when post:" + err.Error())
+		}
+		openlog.Info(
+			fmt.Sprintf("post [%s] success", kv.ID))
+		result.Success = append(result.Success, kv)
+	}
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func getFailedKV(errCode int32, errMsg string, key string, result *model.DocRespOfUpload) {

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: [wip]add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r654757056



##########
File path: pkg/common/common.go
##########
@@ -38,6 +38,7 @@ const (
 	QueryParamIP           = "ip"
 	QueryParamURLPath      = "urlPath"
 	QueryParamUserAgent    = "userAgent"
+	QueryParamOverridden   = "overridden"

Review comment:
       should be override

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {

Review comment:
       这里开始都可以抽取到一个函数,用于处理一个keyvalue,带覆盖策略

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(overridden, common.Stop) && stopped {
+			openlog.Info(fmt.Sprintf("stop create kv %s", kv.Key))
+			getFailedKV(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		domain := ReadDomain(rctx.Ctx)
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err = validator.Validate(kv)
+		if err != nil {
+			getFailedKV(config.ErrInvalidParams, err.Error(), key, result)
+			continue
+		}
+		err = quota.PreCreate("", kv.Domain, "", 1)
+		if err != nil {
+			if err == quota.ErrReached {
+				openlog.Info(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
+				getFailedKV(config.ErrNotEnoughQuota, err.Error(), key, result)
+				continue
+			}
+			openlog.Error(err.Error())
+			getFailedKV(config.ErrInternal, "quota check failed", key, result)
+			continue
+		}
+		var kvOld *model.KVDoc
+		kvOld, err = service.KVService.Create(rctx.Ctx, kv)
+		kv.ID = kvOld.ID
+		if err != nil {
+			openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
+			if err == session.ErrKVAlreadyExists {
+				if strings.EqualFold(overridden, common.Skip) {
+					openlog.Info(fmt.Sprintf("skip create kv %s", kv.Key))
+					getFailedKV(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", key, result)
+				} else if strings.EqualFold(overridden, common.Force) {
+					kvReq := new(model.UpdateKVRequest)
+					kvReq.ID = kv.ID
+					kvReq.Value = kv.Value
+					kvReq.Domain = domain
+					kvReq.Project = project
+					kvReq.Status = kv.Status
+					kv, err = service.KVService.Update(rctx.Ctx, kvReq)
+					result.Success = append(result.Success, kv)
+				} else {
+					getFailedKV(config.ErrRecordAlreadyExists, err.Error(), key, result)
+				}
+				stopped = true
+				continue
+			}
+			getFailedKV(config.ErrInternal, "create kv failed", key, result)
+			continue
+		}
+		err = pubsub.Publish(&pubsub.KVChangeEvent{
+			Key:      kv.Key,
+			Labels:   kv.Labels,
+			Project:  project,
+			DomainID: kv.Domain,
+			Action:   pubsub.ActionPut,
+		})
+		if err != nil {
+			openlog.Warn("lost kv change event when post:" + err.Error())
+		}
+		openlog.Info(
+			fmt.Sprintf("post [%s] success", kv.ID))
+		result.Success = append(result.Success, kv)
+	}
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func getFailedKV(errCode int32, errMsg string, key string, result *model.DocRespOfUpload) {

Review comment:
       改名appendFailedKVResult会更好

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -492,3 +492,168 @@ func TestKVResource_DeleteList(t *testing.T) {
 		assert.Equal(t, 0, len(result.Data))
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	var ids []string
+	t.Run("post all kvs success", func(t *testing.T) {
+		kvs := &[]model.KVDoc{
+			{
+				Key:       "1",
+				Value:     "1",
+				Labels:    map[string]string{"1": "1"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+			{
+				Key:       "2",
+				Value:     "2",
+				Labels:    map[string]string{"2": "2"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+			{
+				Key:       "3",
+				Value:     "3",
+				Labels:    map[string]string{"3": "3"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+		}
+		j, _ := json.Marshal(kvs)
+		r, _ := http.NewRequest("POST", "/v1/kv_test_upload/kie/file", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.NotEmpty(t, data.Success)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 3, len(data.Success))
+	})
+	t.Run("post part of kvs success", func(t *testing.T) {
+		kvs := &[]model.KVDoc{
+			{
+				Key:       "1",
+				Value:     "1",
+				Labels:    map[string]string{"1": "1"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+			{
+				Key:       "4",
+				Value:     "4",
+				Labels:    map[string]string{"2": "2"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+			{
+				Key:       "5",
+				Value:     "5",
+				Labels:    map[string]string{"3": "3"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+		}
+		j, _ := json.Marshal(kvs)
+		r, _ := http.NewRequest("POST", "/v1/kv_test_upload/kie/file", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+
+		assert.Equal(t, 1, len(data.Failure))

Review comment:
       没写HTTP状态码的断言测试

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(overridden, common.Stop) && stopped {
+			openlog.Info(fmt.Sprintf("stop create kv %s", kv.Key))
+			getFailedKV(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		domain := ReadDomain(rctx.Ctx)
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err = validator.Validate(kv)
+		if err != nil {
+			getFailedKV(config.ErrInvalidParams, err.Error(), key, result)
+			continue
+		}
+		err = quota.PreCreate("", kv.Domain, "", 1)
+		if err != nil {
+			if err == quota.ErrReached {
+				openlog.Info(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
+				getFailedKV(config.ErrNotEnoughQuota, err.Error(), key, result)
+				continue
+			}
+			openlog.Error(err.Error())
+			getFailedKV(config.ErrInternal, "quota check failed", key, result)
+			continue
+		}
+		var kvOld *model.KVDoc
+		kvOld, err = service.KVService.Create(rctx.Ctx, kv)
+		kv.ID = kvOld.ID
+		if err != nil {
+			openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
+			if err == session.ErrKVAlreadyExists {
+				if strings.EqualFold(overridden, common.Skip) {
+					openlog.Info(fmt.Sprintf("skip create kv %s", kv.Key))
+					getFailedKV(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", key, result)
+				} else if strings.EqualFold(overridden, common.Force) {
+					kvReq := new(model.UpdateKVRequest)
+					kvReq.ID = kv.ID
+					kvReq.Value = kv.Value
+					kvReq.Domain = domain
+					kvReq.Project = project
+					kvReq.Status = kv.Status
+					kv, err = service.KVService.Update(rctx.Ctx, kvReq)
+					result.Success = append(result.Success, kv)
+				} else {
+					getFailedKV(config.ErrRecordAlreadyExists, err.Error(), key, result)
+				}
+				stopped = true

Review comment:
       这里改成true是不是意味着,不管是不是override==stop,都会停止?

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(overridden, common.Stop) && stopped {
+			openlog.Info(fmt.Sprintf("stop create kv %s", kv.Key))
+			getFailedKV(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		domain := ReadDomain(rctx.Ctx)

Review comment:
       只需要提取一次domain一次,不需要在for中多次提取

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(overridden, common.Stop) && stopped {
+			openlog.Info(fmt.Sprintf("stop create kv %s", kv.Key))
+			getFailedKV(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		domain := ReadDomain(rctx.Ctx)
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err = validator.Validate(kv)
+		if err != nil {
+			getFailedKV(config.ErrInvalidParams, err.Error(), key, result)
+			continue
+		}
+		err = quota.PreCreate("", kv.Domain, "", 1)

Review comment:
       还没判断是否覆盖,不能确认配额是否满足的




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661920916



##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {

Review comment:
       放到strategy包里面,命名叫Override




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r662065787



##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661310359



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,148 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	factory := new(OverrideType)
+	strategy := factory.getType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, err0 := strategy.Execute(kv, rctx, isDuplicate)

Review comment:
       err0无意义的变量命名

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,148 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	factory := new(OverrideType)

Review comment:
       不用在这里new,直接在OverrideType的定义文件中增加工厂方法即可

##########
File path: server/resource/v1/override_strategy.go
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/go-chassis/v2/server/restful"
+)
+
+var overrideMap = make(map[string]strategyOverride)
+
+func init() {
+	Register()
+}
+
+type OverrideType struct {
+}
+
+type strategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, errsvc.Error)
+}
+
+func Register() {
+	overrideMap["force"] = &Force{}
+	overrideMap["abort"] = &Abort{}
+	overrideMap["skip"] = &Skip{}
+}
+
+func (o *OverrideType) getType(override string) strategyOverride {

Review comment:
       不需要定义struct,直接一个func即可

##########
File path: server/resource/v1/override_force.go
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"fmt"
+	"github.com/apache/servicecomb-kie/pkg/common"
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/apache/servicecomb-kie/server/service"
+	"github.com/go-chassis/cari/config"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/go-chassis/v2/server/restful"
+	"github.com/go-chassis/openlog"
+)
+
+type Force struct {
+}
+
+func (f *Force) Execute(kv *model.KVDoc, rctx *restful.Context, _ bool) (*model.KVDoc, errsvc.Error) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	domain := ReadDomain(rctx.Ctx)
+	inputKV := kv
+	kv, err := postOneKv(rctx, kv)
+	if err.Code == config.ErrRecordAlreadyExists {
+		getKvsByOpts, err0 := getKvByOptions(rctx, inputKV)
+		if err0.Message != "" {
+			openlog.Info(fmt.Sprintf("get record [key: %s, labels: %s] failed", inputKV.Key, inputKV.Labels))
+			return inputKV, err0
+		}
+		kvReq := &model.UpdateKVRequest{
+			ID:      getKvsByOpts[0].ID,
+			Value:   getKvsByOpts[0].Value,
+			Status:  getKvsByOpts[0].Status,
+			Domain:  domain,
+			Project: project,
+		}
+		kv, err := service.KVService.Update(rctx.Ctx, kvReq)
+		if err != nil {
+			openlog.Error(fmt.Sprintf("update record [key: %s, labels: %s] failed", inputKV.Key, inputKV.Labels))
+			return inputKV, errsvc.Error{
+				Code:    config.ErrInternal,
+				Message: err.Error(),
+			}
+		}
+		return kv, errsvc.Error{
+			Code:    0,
+			Message: "",
+		}
+	}
+	if err.Message != "" {
+		return inputKV, err
+	}
+	return kv, errsvc.Error{

Review comment:
       没有错误就返回nil,其他override实现也同步改

##########
File path: server/resource/v1/override_strategy.go
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/go-chassis/v2/server/restful"
+)
+
+var overrideMap = make(map[string]strategyOverride)
+
+func init() {
+	Register()
+}
+
+type OverrideType struct {
+}
+
+type strategyOverride interface {

Review comment:
       strategyOverride要改成public,也就是StrategyOverride

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,162 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels", func(t *testing.T) {

Review comment:
       描述的内容应该是test xxx should xxxx的格式

##########
File path: server/resource/v1/override_strategy.go
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/go-chassis/v2/server/restful"
+)
+
+var overrideMap = make(map[string]strategyOverride)
+
+func init() {
+	Register()
+}
+
+type OverrideType struct {
+}
+
+type strategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, errsvc.Error)
+}
+
+func Register() {
+	overrideMap["force"] = &Force{}
+	overrideMap["abort"] = &Abort{}
+	overrideMap["skip"] = &Skip{}

Review comment:
       改成动态注册方式,也就是提供一个Register(name, StrategyOverride)方法,各个override实现里面的init中调用此方法

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,148 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	factory := new(OverrideType)
+	strategy := factory.getType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, err0 := strategy.Execute(kv, rctx, isDuplicate)
+		if err0.Message != "" {
+			if err0.Code == config.ErrRecordAlreadyExists {
+				isDuplicate = true
+			}
+			appendFailedKVResult(err0, kv, result)
+		} else {
+			checkKvChangeEvent(kv)
+			result.Success = append(result.Success, kv)
+		}
+	}
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func getKvByOptions(rctx *restful.Context, kv *model.KVDoc) ([]*model.KVDoc, errsvc.Error) {
+	request := &model.ListKVRequest{
+		Project: kv.Project,
+		Domain:  kv.Domain,
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+	}
+	_, kvsDoc, err := queryListByOpts(rctx, request)
+	return kvsDoc.Data, err
+}
+
+func appendFailedKVResult(err errsvc.Error, kv *model.KVDoc, result *model.DocRespOfUpload) {
+	failedKv := &model.DocFailedOfUpload{
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+		ErrCode: err.Code,
+		ErrMsg:  err.Message,
+	}
+	result.Failure = append(result.Failure, failedKv)
+}
+
 //Post create a kv
 func (r *KVResource) Post(rctx *restful.Context) {
 	var err error
-	project := rctx.ReadPathParameter(common.PathParameterProject)
 	kv := new(model.KVDoc)
 	if err = readRequest(rctx, kv); err != nil {
 		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
 		return
 	}
+	kv, error1 := postOneKv(rctx, kv)
+	if error1.Message != "" {
+		WriteErrResponse(rctx, error1.Code, error1.Message)
+		return
+	}
+	checkKvChangeEvent(kv)
+	err = writeResponse(rctx, kv)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func checkKvChangeEvent(kv *model.KVDoc) {
+	err := pubsub.Publish(&pubsub.KVChangeEvent{
+		Key:      kv.Key,
+		Labels:   kv.Labels,
+		Project:  kv.Project,
+		DomainID: kv.Domain,
+		Action:   pubsub.ActionPut,
+	})
+	if err != nil {
+		openlog.Warn("lost kv change event when post:" + err.Error())
+	}
+	openlog.Info(
+		fmt.Sprintf("post [%s] success", kv.ID))
+}
+
+func postOneKv(rctx *restful.Context, kv *model.KVDoc) (*model.KVDoc, errsvc.Error) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
 	domain := ReadDomain(rctx.Ctx)
 	kv.Domain = domain
 	kv.Project = project
 	if kv.Status == "" {
 		kv.Status = common.StatusDisabled
 	}
-	err = validator.Validate(kv)
+	err := validator.Validate(kv)
 	if err != nil {
-		WriteErrResponse(rctx, config.ErrInvalidParams, err.Error())
-		return
+		return nil, errsvc.Error{
+			Code:    config.ErrInvalidParams,
+			Message: err.Error(),
+		}
 	}
 	err = quota.PreCreate("", kv.Domain, "", 1)
 	if err != nil {
 		if err == quota.ErrReached {
-			openlog.Info(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
-			WriteErrResponse(rctx, config.ErrNotEnoughQuota, err.Error())
-			return
+			openlog.Error(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
+			return nil, errsvc.Error{
+				Code:    config.ErrNotEnoughQuota,
+				Message: err.Error(),
+			}
 		}
 		openlog.Error(err.Error())
-		WriteErrResponse(rctx, config.ErrInternal, "quota check failed")
-		return
+		return nil, errsvc.Error{
+			Code:    config.ErrInternal,
+			Message: "quota check failed",
+		}
 	}
 	kv, err = service.KVService.Create(rctx.Ctx, kv)
 	if err != nil {
 		openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
 		if err == session.ErrKVAlreadyExists {
-			WriteErrResponse(rctx, config.ErrRecordAlreadyExists, err.Error())
-			return
+			return nil, errsvc.Error{
+				Code:    config.ErrRecordAlreadyExists,
+				Message: err.Error(),
+			}
+		}
+		return nil, errsvc.Error{
+			Code:    config.ErrInternal,
+			Message: err.Error(),
 		}
-		WriteErrResponse(rctx, config.ErrInternal, "create kv failed")
-		return
-	}
-	err = pubsub.Publish(&pubsub.KVChangeEvent{
-		Key:      kv.Key,
-		Labels:   kv.Labels,
-		Project:  project,
-		DomainID: kv.Domain,
-		Action:   pubsub.ActionPut,
-	})
-	if err != nil {
-		openlog.Warn("lost kv change event when post:" + err.Error())
 	}
-	openlog.Info(
-		fmt.Sprintf("post [%s] success", kv.ID))
-	err = writeResponse(rctx, kv)
-	if err != nil {
-		openlog.Error(err.Error())
+	return kv, errsvc.Error{

Review comment:
       既然没有error,返回nil即可




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#issuecomment-861443481


   > 对于工作中的PR,前缀加WIP,这样别人有空会给你建议,且表示无需合入
   
   好的


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] tianxiaoliang commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
tianxiaoliang commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661912870



##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {

Review comment:
       OverrideStrategy 是不是顺一些

##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, *errsvc.Error)

Review comment:
       函数的设计中,入参不可以带bool值

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,129 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	strategy := service.GetType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, executeErr := strategy.Execute(kv, rctx, isDuplicate)

Review comment:
       这个for循环逻辑说的是当策略执行错误类型为已存在时,就认为冲突了,然后append这个错误结果,再进入下循环时才会abort了。逻辑其实不够明了直白。3种策略规划的没有错,理想的设计是,for循环里只有strategy.Execute 其他的所有逻辑都在不同策略内实现,而不是跳到下个循环才有结果




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: [wip]add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r654761156



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(overridden, common.Stop) && stopped {
+			openlog.Info(fmt.Sprintf("stop create kv %s", kv.Key))
+			getFailedKV(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		domain := ReadDomain(rctx.Ctx)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661534055



##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))

Review comment:
       增加断言判断应该是相同的kvID

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+	t.Run("test force with the same key and not the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))

Review comment:
       增加断言判断,应该是不同的kvID

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+	t.Run("test force with the same key and not the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+
+	t.Run("test skip, should return 2 success and 1 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "3",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "3",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:       "4",
+				Value:     "1",
+				Labels:    map[string]string{"2": "2"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=skip", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 1, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+		assert.Equal(t, "skip overriding duplicate kvs", data.Failure[0].ErrMsg)
+	})
+	t.Run("test abort, should return 1 success and 2 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "5",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "5",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "6",
+				Value:  "2",
+				Labels: map[string]string{"4": "4"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=abort", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 2, len(data.Failure))
+		assert.Equal(t, 1, len(data.Success))
+		assert.Equal(t, "stop overriding duplicate kv", data.Failure[0].ErrMsg)
+		assert.Equal(t, "stop overriding kvs after reaching the duplicate kv", data.Failure[1].ErrMsg)
+	})

Review comment:
       缺少上传内容非法的场景

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+	t.Run("test force with the same key and not the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+
+	t.Run("test skip, should return 2 success and 1 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "3",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "3",
+				Value:  "1",

Review comment:
       应该是不同的value,并增加断言

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+	t.Run("test force with the same key and not the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+
+	t.Run("test skip, should return 2 success and 1 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "3",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "3",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:       "4",
+				Value:     "1",
+				Labels:    map[string]string{"2": "2"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=skip", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 1, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+		assert.Equal(t, "skip overriding duplicate kvs", data.Failure[0].ErrMsg)
+	})
+	t.Run("test abort, should return 1 success and 2 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "5",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "5",
+				Value:  "2",

Review comment:
       不同的value,增加断言

##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",

Review comment:
       value应该要不一样,并增加断言判断




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661915146



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,129 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	strategy := service.GetType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, executeErr := strategy.Execute(kv, rctx, isDuplicate)

Review comment:
       isDuplicate不需要定义成入参,应该通过判断是否ErrAbort错误来控制逻辑




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661920916



##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {

Review comment:
       放到strategy包里面,命名叫Override




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r658627688



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,51 +41,133 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	logicOfOverride(kvs, rctx, result)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs *[]*model.KVDoc, rctx *restful.Context, result *model.DocRespOfUpload) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	domain := ReadDomain(rctx.Ctx)
+	isDuplicate := false
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(override, common.Stop) && isDuplicate {
+			openlog.Info(fmt.Sprintf("stop overriding kvs after reaching the duplicate kv %s", kv.Key))
+			appendFailedKVResult(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		errCode, errMsg := postOneKv(rctx, kv)
+		if errMsg != "" {
+			isDuplicate = strategyOfDuplicate(errCode, errMsg, kv, result, rctx)
+			continue
+		}
+		checkKvChangeEvent(kv)
+		result.Success = append(result.Success, kv)
+	}
+}
+
+func strategyOfDuplicate(errCode int32, errMsg string,

Review comment:
       判断是否重复放在外面了,只有重复才会进来,force/skip/stop对于重复的处理不一样

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,51 +41,133 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	logicOfOverride(kvs, rctx, result)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs *[]*model.KVDoc, rctx *restful.Context, result *model.DocRespOfUpload) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	domain := ReadDomain(rctx.Ctx)
+	isDuplicate := false
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(override, common.Stop) && isDuplicate {
+			openlog.Info(fmt.Sprintf("stop overriding kvs after reaching the duplicate kv %s", kv.Key))
+			appendFailedKVResult(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		errCode, errMsg := postOneKv(rctx, kv)
+		if errMsg != "" {
+			isDuplicate = strategyOfDuplicate(errCode, errMsg, kv, result, rctx)
+			continue
+		}
+		checkKvChangeEvent(kv)
+		result.Success = append(result.Success, kv)
+	}
+}
+
+func strategyOfDuplicate(errCode int32, errMsg string,
+	kv *model.KVDoc, result *model.DocRespOfUpload, rctx *restful.Context) bool {
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	if errCode != config.ErrRecordAlreadyExists {
+		appendFailedKVResult(errCode, errMsg, kv.Key, result)
+		return false
+	}
+	if override == common.Skip {
+		openlog.Info(fmt.Sprintf("skip overriding duplicate kv %s", kv.Key))
+		appendFailedKVResult(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", kv.Key, result)
+	} else if override == common.Force {
+		request := &model.ListKVRequest{
+			Project: kv.Project,
+			Domain:  kv.Domain,
+			Key:     kv.Key,
+			Labels:  kv.Labels,
+		}
+		code, msg, _, kvsDoc := queryListByOpts(rctx, request)
+		if msg != "" {
+			openlog.Info(fmt.Sprintf("get kv %s failed", kv.Key))
+			appendFailedKVResult(code, msg, kv.Key, result)
+		} else {
+			kvReq := new(model.UpdateKVRequest)
+			kvReq.ID = kvsDoc.Data[0].ID
+			kvReq.Value = kv.Value
+			kvReq.Domain = kv.Domain
+			kvReq.Project = kv.Project
+			kvReq.Status = kv.Status
+			key := kv.Key
+			kv, err := service.KVService.Update(rctx.Ctx, kvReq)
+			if err != nil {
+				openlog.Info(fmt.Sprintf("update kv %s failed", key))

Review comment:
       done

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -93,11 +176,44 @@ func (r *KVResource) Post(rctx *restful.Context) {
 	}
 	openlog.Info(
 		fmt.Sprintf("post [%s] success", kv.ID))
-	err = writeResponse(rctx, kv)
+}
+
+func postOneKv(rctx *restful.Context, kv *model.KVDoc) (int32, string) {

Review comment:
       done

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -93,11 +176,44 @@ func (r *KVResource) Post(rctx *restful.Context) {
 	}
 	openlog.Info(
 		fmt.Sprintf("post [%s] success", kv.ID))
-	err = writeResponse(rctx, kv)
+}
+
+func postOneKv(rctx *restful.Context, kv *model.KVDoc) (int32, string) {
+	kv.Domain = ReadDomain(rctx.Ctx)
+	kv.Project = rctx.ReadPathParameter(common.PathParameterProject)
+	if kv.Status == "" {
+		kv.Status = common.StatusDisabled
+	}
+	errCode, errMsg := inputCheck(kv)
+	if errMsg != "" {
+		return errCode, errMsg
+	}
+	kv, err := service.KVService.Create(rctx.Ctx, kv)
 	if err != nil {
-		openlog.Error(err.Error())
+		openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
+		if err == session.ErrKVAlreadyExists {
+			return config.ErrRecordAlreadyExists, err.Error()
+		}
+		return config.ErrInternal, "create kv failed"
 	}
+	return 0, ""
+}
 
+func inputCheck(kv *model.KVDoc) (int32, string) {

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661546967



##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+	t.Run("test force with the same key and not the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+
+	t.Run("test skip, should return 2 success and 1 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "3",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "3",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:       "4",
+				Value:     "1",
+				Labels:    map[string]string{"2": "2"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=skip", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 1, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+		assert.Equal(t, "skip overriding duplicate kvs", data.Failure[0].ErrMsg)
+	})
+	t.Run("test abort, should return 1 success and 2 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "5",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "5",
+				Value:  "2",

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis closed pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis closed pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] tianxiaoliang commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
tianxiaoliang commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661912961



##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, *errsvc.Error)

Review comment:
       函数的设计中,入参不可以带bool值,关于如何消除,可以看下一个评论




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r660238890



##########
File path: server/resource/v1/common.go
##########
@@ -248,6 +248,20 @@ func checkDomainAndProject(domain, project string) error {
 }
 
 func queryAndResponse(rctx *restful.Context, request *model.ListKVRequest) {
+	errCode, err, rev, kv := queryListByOpts(rctx, request)
+	if err != nil {
+		WriteErrResponse(rctx, errCode, err.Error())
+		return
+	}
+	rctx.ReadResponseWriter().Header().Set(common.HeaderRevision, strconv.FormatInt(rev, 10))
+	err = writeResponse(rctx, kv)
+	rctx.ReadRestfulRequest().SetAttribute(common.RespBodyContextKey, kv.Data)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func queryListByOpts(rctx *restful.Context, request *model.ListKVRequest) (int32, error, int64, *model.KVResponse) {

Review comment:
       1、int32, error 可以使用结构cari/pkg/errsvc来包装
   2、一般错误输出参数,排序放最后

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +40,124 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := logicOfOverride(kvs[:], rctx)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs []*model.KVDoc, rctx *restful.Context) *model.DocRespOfUpload {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	domain := ReadDomain(rctx.Ctx)
+	isDuplicate := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		if override == common.Abort && isDuplicate {
+			openlog.Info(fmt.Sprintf("stop overriding kvs after reaching the duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+			appendFailedKVResult(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", kv, result)
+			continue
+		}
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err := validator.Validate(kv)
+		if err != nil {
+			appendFailedKVResult(config.ErrInvalidParams, err.Error(), kv, result)
+			continue
+		}
+		inputKV := kv
+		errCode, err := postOneKv(rctx, kv)
+		if errCode == config.ErrRecordAlreadyExists {
+			isDuplicate = true
+			strategyOfDuplicate(kv, result, rctx)
+			continue
+		}
+		if err != nil {
+			appendFailedKVResult(errCode, err.Error(), inputKV, result)
+			continue
+		}
+		checkKvChangeEvent(kv)
+		result.Success = append(result.Success, kv)
+	}
+	return result
+}
+
+func getKvByOptions(rctx *restful.Context, kv *model.KVDoc) (int32, error, []*model.KVDoc) {
+	request := &model.ListKVRequest{
+		Project: kv.Project,
+		Domain:  kv.Domain,
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+	}
+	code, err, _, kvsDoc := queryListByOpts(rctx, request)
+	if err != nil {
+		return code, err, nil
+	}
+	return 0, nil, kvsDoc.Data
+}
+
+func strategyOfDuplicate(kv *model.KVDoc, result *model.DocRespOfUpload, rctx *restful.Context) {
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	if override == common.Skip {
+		openlog.Info(fmt.Sprintf("skip overriding duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+		appendFailedKVResult(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", kv, result)
+	} else if override == common.Abort {
+		openlog.Info(fmt.Sprintf("stop overriding duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+		appendFailedKVResult(config.ErrRecordAlreadyExists, "stop overriding duplicate kv", kv, result)
+	} else {
+		errCode, err, getKvsByOpts := getKvByOptions(rctx, kv)
+		if err != nil {
+			openlog.Info(fmt.Sprintf("get record [key: %s, labels: %s] failed", kv.Key, kv.Labels))
+			appendFailedKVResult(errCode, err.Error(), kv, result)
+			return
+		}
+		kvReq := &model.UpdateKVRequest{
+			ID:      getKvsByOpts[0].ID,
+			Value:   kv.Value,
+			Domain:  kv.Domain,
+			Project: kv.Project,
+			Status:  kv.Status,
+		}
+		kvNew, err := service.KVService.Update(rctx.Ctx, kvReq)
+		if err != nil {
+			openlog.Error(fmt.Sprintf("update record [key: %s, labels: %s] failed", kv.Key, kv.Labels))
+			appendFailedKVResult(config.ErrInternal, err.Error(), kv, result)
+			return
+		}
+		checkKvChangeEvent(kvNew)
+		result.Success = append(result.Success, kvNew)
+	}
+}
+
+func appendFailedKVResult(errCode int32, errMsg string, kv *model.KVDoc, result *model.DocRespOfUpload) {

Review comment:
       使用cari/pkg/errsvc

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {

Review comment:
       没解决,期望是通过抽象接口,使用工厂+策略模式解决




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r658627115



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(overridden, common.Stop) && stopped {
+			openlog.Info(fmt.Sprintf("stop create kv %s", kv.Key))
+			getFailedKV(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		domain := ReadDomain(rctx.Ctx)
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err = validator.Validate(kv)
+		if err != nil {
+			getFailedKV(config.ErrInvalidParams, err.Error(), key, result)
+			continue
+		}
+		err = quota.PreCreate("", kv.Domain, "", 1)
+		if err != nil {
+			if err == quota.ErrReached {
+				openlog.Info(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
+				getFailedKV(config.ErrNotEnoughQuota, err.Error(), key, result)
+				continue
+			}
+			openlog.Error(err.Error())
+			getFailedKV(config.ErrInternal, "quota check failed", key, result)
+			continue
+		}
+		var kvOld *model.KVDoc
+		kvOld, err = service.KVService.Create(rctx.Ctx, kv)
+		kv.ID = kvOld.ID
+		if err != nil {
+			openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
+			if err == session.ErrKVAlreadyExists {
+				if strings.EqualFold(overridden, common.Skip) {
+					openlog.Info(fmt.Sprintf("skip create kv %s", kv.Key))
+					getFailedKV(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", key, result)
+				} else if strings.EqualFold(overridden, common.Force) {
+					kvReq := new(model.UpdateKVRequest)
+					kvReq.ID = kv.ID
+					kvReq.Value = kv.Value
+					kvReq.Domain = domain
+					kvReq.Project = project
+					kvReq.Status = kv.Status
+					kv, err = service.KVService.Update(rctx.Ctx, kvReq)
+					result.Success = append(result.Success, kv)
+				} else {
+					getFailedKV(config.ErrRecordAlreadyExists, err.Error(), key, result)
+				}
+				stopped = true

Review comment:
       只有override==stop并且isDuplicate==true才会停止

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,51 +41,133 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	logicOfOverride(kvs, rctx, result)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs *[]*model.KVDoc, rctx *restful.Context, result *model.DocRespOfUpload) {

Review comment:
       done

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,51 +41,133 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := new([]*model.KVDoc)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r658628817



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +40,130 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := make([]*model.KVDoc, 0)
+	if err = readRequest(rctx, &kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := logicOfOverride(kvs[:], rctx)

Review comment:
       kvs已经是slice,不用再生成一个新slice(kvs[:] -> kvs)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661526126



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,129 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	strategy := getType(override)

Review comment:
       建议抽取到server/service/mongo/strategy包中




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661318191



##########
File path: server/resource/v1/common.go
##########
@@ -263,19 +278,21 @@ func queryAndResponse(rctx *restful.Context, request *model.ListKVRequest) {
 	}
 	rev, err := service.RevisionService.GetRevision(rctx.Ctx, request.Domain)
 	if err != nil {
-		WriteErrResponse(rctx, config.ErrInternal, err.Error())
-		return
+		return rev, nil, errsvc.Error{

Review comment:
       errsvc有NewError方法,其他地方一并修改




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661545950



##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,160 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "1",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+	t.Run("test force with the same key and not the same labels, should return 2 success and 0 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"1": "1"},
+			},
+			{
+				Key:    "2",
+				Value:  "2",
+				Labels: map[string]string{"2": "2"},
+			},
+		}
+		j, _ := json.Marshal(input)
+		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/file?override=force", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.Equal(t, http.StatusOK, resp.Code)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 2, len(data.Success))
+	})
+
+	t.Run("test skip, should return 2 success and 1 failure", func(t *testing.T) {
+		input := new(v1.KVUploadBody)
+		input.Data = []*model.KVDoc{
+			{
+				Key:    "3",
+				Value:  "1",
+				Labels: map[string]string{"2": "2"},
+			},
+			{
+				Key:    "3",
+				Value:  "1",

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r658626369



##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -492,3 +492,168 @@ func TestKVResource_DeleteList(t *testing.T) {
 		assert.Equal(t, 0, len(result.Data))
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	var ids []string
+	t.Run("post all kvs success", func(t *testing.T) {
+		kvs := &[]model.KVDoc{
+			{
+				Key:       "1",
+				Value:     "1",
+				Labels:    map[string]string{"1": "1"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+			{
+				Key:       "2",
+				Value:     "2",
+				Labels:    map[string]string{"2": "2"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+			{
+				Key:       "3",
+				Value:     "3",
+				Labels:    map[string]string{"3": "3"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+		}
+		j, _ := json.Marshal(kvs)
+		r, _ := http.NewRequest("POST", "/v1/kv_test_upload/kie/file", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+		assert.NotEmpty(t, data.Success)
+		assert.Equal(t, 0, len(data.Failure))
+		assert.Equal(t, 3, len(data.Success))
+	})
+	t.Run("post part of kvs success", func(t *testing.T) {
+		kvs := &[]model.KVDoc{
+			{
+				Key:       "1",
+				Value:     "1",
+				Labels:    map[string]string{"1": "1"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+			{
+				Key:       "4",
+				Value:     "4",
+				Labels:    map[string]string{"2": "2"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+			{
+				Key:       "5",
+				Value:     "5",
+				Labels:    map[string]string{"3": "3"},
+				ValueType: "text",
+				Status:    "enabled",
+			},
+		}
+		j, _ := json.Marshal(kvs)
+		r, _ := http.NewRequest("POST", "/v1/kv_test_upload/kie/file", bytes.NewBuffer(j))
+		r.Header.Set("Content-Type", "application/json")
+		kvr := &v1.KVResource{}
+		c, _ := restfultest.New(kvr, nil)
+		resp := httptest.NewRecorder()
+		c.ServeHTTP(resp, r)
+
+		body, err := ioutil.ReadAll(resp.Body)
+		assert.NoError(t, err)
+		data := &model.DocRespOfUpload{
+			Success: []*model.KVDoc{},
+			Failure: []*model.DocFailedOfUpload{},
+		}
+		err = json.Unmarshal(body, data)
+		assert.NoError(t, err)
+
+		assert.Equal(t, 1, len(data.Failure))

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661362705



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,148 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	factory := new(OverrideType)
+	strategy := factory.getType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, err0 := strategy.Execute(kv, rctx, isDuplicate)
+		if err0.Message != "" {
+			if err0.Code == config.ErrRecordAlreadyExists {
+				isDuplicate = true
+			}
+			appendFailedKVResult(err0, kv, result)
+		} else {
+			checkKvChangeEvent(kv)
+			result.Success = append(result.Success, kv)
+		}
+	}
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func getKvByOptions(rctx *restful.Context, kv *model.KVDoc) ([]*model.KVDoc, errsvc.Error) {
+	request := &model.ListKVRequest{
+		Project: kv.Project,
+		Domain:  kv.Domain,
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+	}
+	_, kvsDoc, err := queryListByOpts(rctx, request)
+	return kvsDoc.Data, err
+}
+
+func appendFailedKVResult(err errsvc.Error, kv *model.KVDoc, result *model.DocRespOfUpload) {
+	failedKv := &model.DocFailedOfUpload{
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+		ErrCode: err.Code,
+		ErrMsg:  err.Message,
+	}
+	result.Failure = append(result.Failure, failedKv)
+}
+
 //Post create a kv
 func (r *KVResource) Post(rctx *restful.Context) {
 	var err error
-	project := rctx.ReadPathParameter(common.PathParameterProject)
 	kv := new(model.KVDoc)
 	if err = readRequest(rctx, kv); err != nil {
 		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
 		return
 	}
+	kv, error1 := postOneKv(rctx, kv)
+	if error1.Message != "" {
+		WriteErrResponse(rctx, error1.Code, error1.Message)
+		return
+	}
+	checkKvChangeEvent(kv)
+	err = writeResponse(rctx, kv)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func checkKvChangeEvent(kv *model.KVDoc) {
+	err := pubsub.Publish(&pubsub.KVChangeEvent{
+		Key:      kv.Key,
+		Labels:   kv.Labels,
+		Project:  kv.Project,
+		DomainID: kv.Domain,
+		Action:   pubsub.ActionPut,
+	})
+	if err != nil {
+		openlog.Warn("lost kv change event when post:" + err.Error())
+	}
+	openlog.Info(
+		fmt.Sprintf("post [%s] success", kv.ID))
+}
+
+func postOneKv(rctx *restful.Context, kv *model.KVDoc) (*model.KVDoc, errsvc.Error) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
 	domain := ReadDomain(rctx.Ctx)
 	kv.Domain = domain
 	kv.Project = project
 	if kv.Status == "" {
 		kv.Status = common.StatusDisabled
 	}
-	err = validator.Validate(kv)
+	err := validator.Validate(kv)
 	if err != nil {
-		WriteErrResponse(rctx, config.ErrInvalidParams, err.Error())
-		return
+		return nil, errsvc.Error{
+			Code:    config.ErrInvalidParams,
+			Message: err.Error(),
+		}
 	}
 	err = quota.PreCreate("", kv.Domain, "", 1)
 	if err != nil {
 		if err == quota.ErrReached {
-			openlog.Info(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
-			WriteErrResponse(rctx, config.ErrNotEnoughQuota, err.Error())
-			return
+			openlog.Error(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
+			return nil, errsvc.Error{
+				Code:    config.ErrNotEnoughQuota,
+				Message: err.Error(),
+			}
 		}
 		openlog.Error(err.Error())
-		WriteErrResponse(rctx, config.ErrInternal, "quota check failed")
-		return
+		return nil, errsvc.Error{
+			Code:    config.ErrInternal,
+			Message: "quota check failed",
+		}
 	}
 	kv, err = service.KVService.Create(rctx.Ctx, kv)
 	if err != nil {
 		openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
 		if err == session.ErrKVAlreadyExists {
-			WriteErrResponse(rctx, config.ErrRecordAlreadyExists, err.Error())
-			return
+			return nil, errsvc.Error{
+				Code:    config.ErrRecordAlreadyExists,
+				Message: err.Error(),
+			}
+		}
+		return nil, errsvc.Error{
+			Code:    config.ErrInternal,
+			Message: err.Error(),
 		}
-		WriteErrResponse(rctx, config.ErrInternal, "create kv failed")
-		return
-	}
-	err = pubsub.Publish(&pubsub.KVChangeEvent{
-		Key:      kv.Key,
-		Labels:   kv.Labels,
-		Project:  project,
-		DomainID: kv.Domain,
-		Action:   pubsub.ActionPut,
-	})
-	if err != nil {
-		openlog.Warn("lost kv change event when post:" + err.Error())
 	}
-	openlog.Info(
-		fmt.Sprintf("post [%s] success", kv.ID))
-	err = writeResponse(rctx, kv)
-	if err != nil {
-		openlog.Error(err.Error())
+	return kv, errsvc.Error{

Review comment:
       done

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,148 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	factory := new(OverrideType)
+	strategy := factory.getType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, err0 := strategy.Execute(kv, rctx, isDuplicate)

Review comment:
       done

##########
File path: server/resource/v1/override_force.go
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"fmt"
+	"github.com/apache/servicecomb-kie/pkg/common"
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/apache/servicecomb-kie/server/service"
+	"github.com/go-chassis/cari/config"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/go-chassis/v2/server/restful"
+	"github.com/go-chassis/openlog"
+)
+
+type Force struct {
+}
+
+func (f *Force) Execute(kv *model.KVDoc, rctx *restful.Context, _ bool) (*model.KVDoc, errsvc.Error) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	domain := ReadDomain(rctx.Ctx)
+	inputKV := kv
+	kv, err := postOneKv(rctx, kv)
+	if err.Code == config.ErrRecordAlreadyExists {
+		getKvsByOpts, err0 := getKvByOptions(rctx, inputKV)
+		if err0.Message != "" {
+			openlog.Info(fmt.Sprintf("get record [key: %s, labels: %s] failed", inputKV.Key, inputKV.Labels))
+			return inputKV, err0
+		}
+		kvReq := &model.UpdateKVRequest{
+			ID:      getKvsByOpts[0].ID,
+			Value:   getKvsByOpts[0].Value,
+			Status:  getKvsByOpts[0].Status,
+			Domain:  domain,
+			Project: project,
+		}
+		kv, err := service.KVService.Update(rctx.Ctx, kvReq)
+		if err != nil {
+			openlog.Error(fmt.Sprintf("update record [key: %s, labels: %s] failed", inputKV.Key, inputKV.Labels))
+			return inputKV, errsvc.Error{
+				Code:    config.ErrInternal,
+				Message: err.Error(),
+			}
+		}
+		return kv, errsvc.Error{
+			Code:    0,
+			Message: "",
+		}
+	}
+	if err.Message != "" {
+		return inputKV, err
+	}
+	return kv, errsvc.Error{

Review comment:
       done

##########
File path: server/resource/v1/common.go
##########
@@ -248,6 +249,20 @@ func checkDomainAndProject(domain, project string) error {
 }
 
 func queryAndResponse(rctx *restful.Context, request *model.ListKVRequest) {
+	rev, kv, err0 := queryListByOpts(rctx, request)

Review comment:
       done

##########
File path: server/resource/v1/common.go
##########
@@ -263,19 +278,21 @@ func queryAndResponse(rctx *restful.Context, request *model.ListKVRequest) {
 	}
 	rev, err := service.RevisionService.GetRevision(rctx.Ctx, request.Domain)
 	if err != nil {
-		WriteErrResponse(rctx, config.ErrInternal, err.Error())
-		return
+		return rev, nil, errsvc.Error{

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] tianxiaoliang merged pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
tianxiaoliang merged pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r658626488



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {

Review comment:
       done

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(overridden, common.Stop) && stopped {
+			openlog.Info(fmt.Sprintf("stop create kv %s", kv.Key))
+			getFailedKV(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		domain := ReadDomain(rctx.Ctx)
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err = validator.Validate(kv)
+		if err != nil {
+			getFailedKV(config.ErrInvalidParams, err.Error(), key, result)
+			continue
+		}
+		err = quota.PreCreate("", kv.Domain, "", 1)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r662065934



##########
File path: server/service/mongo/init.go
##########
@@ -34,4 +35,7 @@ func init() {
 	service.HistoryService = &history.Service{}
 	service.TrackService = &track.Service{}
 	service.RevisionService = &counter.Service{}
+	service.StrategyService = &strategy.Abort{}
+	service.StrategyService = &strategy.Force{}
+	service.StrategyService = &strategy.Skip{}

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661348186



##########
File path: server/resource/v1/kv_resource_test.go
##########
@@ -367,6 +367,162 @@ func TestKVResource_List(t *testing.T) {
 
 	})
 }
+func TestKVResource_Upload(t *testing.T) {
+	t.Run("test force with the same key and the same labels", func(t *testing.T) {

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661539600



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,129 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	strategy := getType(override)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] tianxiaoliang commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
tianxiaoliang commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661915996



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,129 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	strategy := service.GetType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, executeErr := strategy.Execute(kv, rctx, isDuplicate)

Review comment:
       这个for循环逻辑说的是当策略执行错误类型为已存在时,就认为冲突了,然后append这个错误结果,再进入下循环时才会abort。逻辑其实不够明了直白。3种策略规划的没有错,理想的设计是,for循环里只有strategy.Execute 其他的所有逻辑都在不同策略内实现,而不是跳到下个循环才有结果




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661919840



##########
File path: server/service/mongo/init.go
##########
@@ -34,4 +35,7 @@ func init() {
 	service.HistoryService = &history.Service{}
 	service.TrackService = &track.Service{}
 	service.RevisionService = &counter.Service{}
+	service.StrategyService = &strategy.Abort{}
+	service.StrategyService = &strategy.Force{}
+	service.StrategyService = &strategy.Skip{}

Review comment:
       这个逻辑有问题,不就是永远都是service.StrategyService = &strategy.Skip{}

##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, *errsvc.Error)

Review comment:
       一般ctx放入参第一位




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661441257



##########
File path: server/resource/v1/override_strategy.go
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/go-chassis/v2/server/restful"
+)
+
+var overrideMap = make(map[string]strategyOverride)
+
+func init() {
+	Register()
+}
+
+type OverrideType struct {
+}
+
+type strategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, errsvc.Error)
+}
+
+func Register() {
+	overrideMap["force"] = &Force{}
+	overrideMap["abort"] = &Abort{}
+	overrideMap["skip"] = &Skip{}
+}
+
+func (o *OverrideType) getType(override string) strategyOverride {

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661315702



##########
File path: server/resource/v1/common.go
##########
@@ -248,6 +249,20 @@ func checkDomainAndProject(domain, project string) error {
 }
 
 func queryAndResponse(rctx *restful.Context, request *model.ListKVRequest) {
+	rev, kv, err0 := queryListByOpts(rctx, request)

Review comment:
       err0无意义的命名




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661937938



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,129 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	strategy := service.GetType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, executeErr := strategy.Execute(kv, rctx, isDuplicate)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] tianxiaoliang commented on pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
tianxiaoliang commented on pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#issuecomment-861206302


   对于工作中的PR,前缀加WIP,这样别人有空会给你建议,且表示无需合入


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r658628817



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +40,130 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := make([]*model.KVDoc, 0)
+	if err = readRequest(rctx, &kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := logicOfOverride(kvs[:], rctx)

Review comment:
       kvs已经是slice,不用再生成一个新slice(kvs[:] -> kvs)

##########
File path: server/resource/v1/common.go
##########
@@ -248,6 +248,20 @@ func checkDomainAndProject(domain, project string) error {
 }
 
 func queryAndResponse(rctx *restful.Context, request *model.ListKVRequest) {
+	errCode, err, rev, kv := queryListByOpts(rctx, request)
+	if err != nil {
+		WriteErrResponse(rctx, errCode, err.Error())
+		return
+	}
+	rctx.ReadResponseWriter().Header().Set(common.HeaderRevision, strconv.FormatInt(rev, 10))
+	err = writeResponse(rctx, kv)
+	rctx.ReadRestfulRequest().SetAttribute(common.RespBodyContextKey, kv.Data)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func queryListByOpts(rctx *restful.Context, request *model.ListKVRequest) (int32, error, int64, *model.KVResponse) {

Review comment:
       1、int32, error 可以使用结构cari/pkg/errsvc来包装
   2、一般错误输出参数,排序放最后

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +40,124 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := logicOfOverride(kvs[:], rctx)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs []*model.KVDoc, rctx *restful.Context) *model.DocRespOfUpload {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	domain := ReadDomain(rctx.Ctx)
+	isDuplicate := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		if override == common.Abort && isDuplicate {
+			openlog.Info(fmt.Sprintf("stop overriding kvs after reaching the duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+			appendFailedKVResult(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", kv, result)
+			continue
+		}
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err := validator.Validate(kv)
+		if err != nil {
+			appendFailedKVResult(config.ErrInvalidParams, err.Error(), kv, result)
+			continue
+		}
+		inputKV := kv
+		errCode, err := postOneKv(rctx, kv)
+		if errCode == config.ErrRecordAlreadyExists {
+			isDuplicate = true
+			strategyOfDuplicate(kv, result, rctx)
+			continue
+		}
+		if err != nil {
+			appendFailedKVResult(errCode, err.Error(), inputKV, result)
+			continue
+		}
+		checkKvChangeEvent(kv)
+		result.Success = append(result.Success, kv)
+	}
+	return result
+}
+
+func getKvByOptions(rctx *restful.Context, kv *model.KVDoc) (int32, error, []*model.KVDoc) {
+	request := &model.ListKVRequest{
+		Project: kv.Project,
+		Domain:  kv.Domain,
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+	}
+	code, err, _, kvsDoc := queryListByOpts(rctx, request)
+	if err != nil {
+		return code, err, nil
+	}
+	return 0, nil, kvsDoc.Data
+}
+
+func strategyOfDuplicate(kv *model.KVDoc, result *model.DocRespOfUpload, rctx *restful.Context) {
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	if override == common.Skip {
+		openlog.Info(fmt.Sprintf("skip overriding duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+		appendFailedKVResult(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", kv, result)
+	} else if override == common.Abort {
+		openlog.Info(fmt.Sprintf("stop overriding duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+		appendFailedKVResult(config.ErrRecordAlreadyExists, "stop overriding duplicate kv", kv, result)
+	} else {
+		errCode, err, getKvsByOpts := getKvByOptions(rctx, kv)
+		if err != nil {
+			openlog.Info(fmt.Sprintf("get record [key: %s, labels: %s] failed", kv.Key, kv.Labels))
+			appendFailedKVResult(errCode, err.Error(), kv, result)
+			return
+		}
+		kvReq := &model.UpdateKVRequest{
+			ID:      getKvsByOpts[0].ID,
+			Value:   kv.Value,
+			Domain:  kv.Domain,
+			Project: kv.Project,
+			Status:  kv.Status,
+		}
+		kvNew, err := service.KVService.Update(rctx.Ctx, kvReq)
+		if err != nil {
+			openlog.Error(fmt.Sprintf("update record [key: %s, labels: %s] failed", kv.Key, kv.Labels))
+			appendFailedKVResult(config.ErrInternal, err.Error(), kv, result)
+			return
+		}
+		checkKvChangeEvent(kvNew)
+		result.Success = append(result.Success, kvNew)
+	}
+}
+
+func appendFailedKVResult(errCode int32, errMsg string, kv *model.KVDoc, result *model.DocRespOfUpload) {

Review comment:
       使用cari/pkg/errsvc

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {

Review comment:
       没解决,期望是通过抽象接口,使用工厂+策略模式解决




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] little-cui commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
little-cui commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661311087



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,148 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	factory := new(OverrideType)
+	strategy := factory.getType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, err0 := strategy.Execute(kv, rctx, isDuplicate)
+		if err0.Message != "" {
+			if err0.Code == config.ErrRecordAlreadyExists {
+				isDuplicate = true
+			}
+			appendFailedKVResult(err0, kv, result)
+		} else {
+			checkKvChangeEvent(kv)
+			result.Success = append(result.Success, kv)
+		}
+	}
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func getKvByOptions(rctx *restful.Context, kv *model.KVDoc) ([]*model.KVDoc, errsvc.Error) {
+	request := &model.ListKVRequest{
+		Project: kv.Project,
+		Domain:  kv.Domain,
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+	}
+	_, kvsDoc, err := queryListByOpts(rctx, request)
+	return kvsDoc.Data, err
+}
+
+func appendFailedKVResult(err errsvc.Error, kv *model.KVDoc, result *model.DocRespOfUpload) {
+	failedKv := &model.DocFailedOfUpload{
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+		ErrCode: err.Code,
+		ErrMsg:  err.Message,
+	}
+	result.Failure = append(result.Failure, failedKv)
+}
+
 //Post create a kv
 func (r *KVResource) Post(rctx *restful.Context) {
 	var err error
-	project := rctx.ReadPathParameter(common.PathParameterProject)
 	kv := new(model.KVDoc)
 	if err = readRequest(rctx, kv); err != nil {
 		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
 		return
 	}
+	kv, error1 := postOneKv(rctx, kv)
+	if error1.Message != "" {
+		WriteErrResponse(rctx, error1.Code, error1.Message)
+		return
+	}
+	checkKvChangeEvent(kv)
+	err = writeResponse(rctx, kv)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func checkKvChangeEvent(kv *model.KVDoc) {
+	err := pubsub.Publish(&pubsub.KVChangeEvent{
+		Key:      kv.Key,
+		Labels:   kv.Labels,
+		Project:  kv.Project,
+		DomainID: kv.Domain,
+		Action:   pubsub.ActionPut,
+	})
+	if err != nil {
+		openlog.Warn("lost kv change event when post:" + err.Error())
+	}
+	openlog.Info(
+		fmt.Sprintf("post [%s] success", kv.ID))
+}
+
+func postOneKv(rctx *restful.Context, kv *model.KVDoc) (*model.KVDoc, errsvc.Error) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
 	domain := ReadDomain(rctx.Ctx)
 	kv.Domain = domain
 	kv.Project = project
 	if kv.Status == "" {
 		kv.Status = common.StatusDisabled
 	}
-	err = validator.Validate(kv)
+	err := validator.Validate(kv)
 	if err != nil {
-		WriteErrResponse(rctx, config.ErrInvalidParams, err.Error())
-		return
+		return nil, errsvc.Error{
+			Code:    config.ErrInvalidParams,
+			Message: err.Error(),
+		}
 	}
 	err = quota.PreCreate("", kv.Domain, "", 1)
 	if err != nil {
 		if err == quota.ErrReached {
-			openlog.Info(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
-			WriteErrResponse(rctx, config.ErrNotEnoughQuota, err.Error())
-			return
+			openlog.Error(fmt.Sprintf("can not create kv %s@%s, due to quota violation", kv.Key, kv.Project))
+			return nil, errsvc.Error{
+				Code:    config.ErrNotEnoughQuota,
+				Message: err.Error(),
+			}
 		}
 		openlog.Error(err.Error())
-		WriteErrResponse(rctx, config.ErrInternal, "quota check failed")
-		return
+		return nil, errsvc.Error{
+			Code:    config.ErrInternal,
+			Message: "quota check failed",
+		}
 	}
 	kv, err = service.KVService.Create(rctx.Ctx, kv)
 	if err != nil {
 		openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
 		if err == session.ErrKVAlreadyExists {
-			WriteErrResponse(rctx, config.ErrRecordAlreadyExists, err.Error())
-			return
+			return nil, errsvc.Error{
+				Code:    config.ErrRecordAlreadyExists,
+				Message: err.Error(),
+			}
+		}
+		return nil, errsvc.Error{
+			Code:    config.ErrInternal,
+			Message: err.Error(),
 		}
-		WriteErrResponse(rctx, config.ErrInternal, "create kv failed")
-		return
-	}
-	err = pubsub.Publish(&pubsub.KVChangeEvent{
-		Key:      kv.Key,
-		Labels:   kv.Labels,
-		Project:  project,
-		DomainID: kv.Domain,
-		Action:   pubsub.ActionPut,
-	})
-	if err != nil {
-		openlog.Warn("lost kv change event when post:" + err.Error())
 	}
-	openlog.Info(
-		fmt.Sprintf("post [%s] success", kv.ID))
-	err = writeResponse(rctx, kv)
-	if err != nil {
-		openlog.Error(err.Error())
+	return kv, errsvc.Error{

Review comment:
       既然没有error,返回nil即可,其他地方也要改过来




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661937862



##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, *errsvc.Error)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] aseTo2016 commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
aseTo2016 commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r656921949



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,51 +41,133 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	logicOfOverride(kvs, rctx, result)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs *[]*model.KVDoc, rctx *restful.Context, result *model.DocRespOfUpload) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	domain := ReadDomain(rctx.Ctx)
+	isDuplicate := false
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(override, common.Stop) && isDuplicate {
+			openlog.Info(fmt.Sprintf("stop overriding kvs after reaching the duplicate kv %s", kv.Key))
+			appendFailedKVResult(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		errCode, errMsg := postOneKv(rctx, kv)
+		if errMsg != "" {
+			isDuplicate = strategyOfDuplicate(errCode, errMsg, kv, result, rctx)
+			continue
+		}
+		checkKvChangeEvent(kv)
+		result.Success = append(result.Success, kv)
+	}
+}
+
+func strategyOfDuplicate(errCode int32, errMsg string,

Review comment:
       strategyOfDuplicate只做是否是重复的判断,不要做那么复杂的逻辑

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,51 +41,133 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	logicOfOverride(kvs, rctx, result)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs *[]*model.KVDoc, rctx *restful.Context, result *model.DocRespOfUpload) {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	domain := ReadDomain(rctx.Ctx)
+	isDuplicate := false
+	for _, kv := range *kvs {
+		if kv == nil {
+			continue
+		}
+		key := kv.Key
+		if strings.EqualFold(override, common.Stop) && isDuplicate {
+			openlog.Info(fmt.Sprintf("stop overriding kvs after reaching the duplicate kv %s", kv.Key))
+			appendFailedKVResult(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", key, result)
+			continue
+		}
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		errCode, errMsg := postOneKv(rctx, kv)
+		if errMsg != "" {
+			isDuplicate = strategyOfDuplicate(errCode, errMsg, kv, result, rctx)
+			continue
+		}
+		checkKvChangeEvent(kv)
+		result.Success = append(result.Success, kv)
+	}
+}
+
+func strategyOfDuplicate(errCode int32, errMsg string,
+	kv *model.KVDoc, result *model.DocRespOfUpload, rctx *restful.Context) bool {
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	if errCode != config.ErrRecordAlreadyExists {
+		appendFailedKVResult(errCode, errMsg, kv.Key, result)
+		return false
+	}
+	if override == common.Skip {
+		openlog.Info(fmt.Sprintf("skip overriding duplicate kv %s", kv.Key))
+		appendFailedKVResult(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", kv.Key, result)
+	} else if override == common.Force {
+		request := &model.ListKVRequest{
+			Project: kv.Project,
+			Domain:  kv.Domain,
+			Key:     kv.Key,
+			Labels:  kv.Labels,
+		}
+		code, msg, _, kvsDoc := queryListByOpts(rctx, request)
+		if msg != "" {
+			openlog.Info(fmt.Sprintf("get kv %s failed", kv.Key))
+			appendFailedKVResult(code, msg, kv.Key, result)
+		} else {
+			kvReq := new(model.UpdateKVRequest)
+			kvReq.ID = kvsDoc.Data[0].ID
+			kvReq.Value = kv.Value
+			kvReq.Domain = kv.Domain
+			kvReq.Project = kv.Project
+			kvReq.Status = kv.Status
+			key := kv.Key
+			kv, err := service.KVService.Update(rctx.Ctx, kvReq)
+			if err != nil {
+				openlog.Info(fmt.Sprintf("update kv %s failed", key))

Review comment:
       日志级别改为error

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -93,11 +176,44 @@ func (r *KVResource) Post(rctx *restful.Context) {
 	}
 	openlog.Info(
 		fmt.Sprintf("post [%s] success", kv.ID))
-	err = writeResponse(rctx, kv)
+}
+
+func postOneKv(rctx *restful.Context, kv *model.KVDoc) (int32, string) {

Review comment:
       返回error就行,不用返回string

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,51 +41,133 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := new([]*model.KVDoc)

Review comment:
       定义kvs := make([]*model.KVDoc, 0, 5)
   readRequest(rctx, &kvs)传入指针即可

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -93,11 +176,44 @@ func (r *KVResource) Post(rctx *restful.Context) {
 	}
 	openlog.Info(
 		fmt.Sprintf("post [%s] success", kv.ID))
-	err = writeResponse(rctx, kv)
+}
+
+func postOneKv(rctx *restful.Context, kv *model.KVDoc) (int32, string) {
+	kv.Domain = ReadDomain(rctx.Ctx)
+	kv.Project = rctx.ReadPathParameter(common.PathParameterProject)
+	if kv.Status == "" {
+		kv.Status = common.StatusDisabled
+	}
+	errCode, errMsg := inputCheck(kv)
+	if errMsg != "" {
+		return errCode, errMsg
+	}
+	kv, err := service.KVService.Create(rctx.Ctx, kv)
 	if err != nil {
-		openlog.Error(err.Error())
+		openlog.Error(fmt.Sprintf("post err:%s", err.Error()))
+		if err == session.ErrKVAlreadyExists {
+			return config.ErrRecordAlreadyExists, err.Error()
+		}
+		return config.ErrInternal, "create kv failed"
 	}
+	return 0, ""
+}
 
+func inputCheck(kv *model.KVDoc) (int32, string) {

Review comment:
       同上




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661157879



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +40,124 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := logicOfOverride(kvs[:], rctx)
+	err = writeResponse(rctx, result)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func logicOfOverride(kvs []*model.KVDoc, rctx *restful.Context) *model.DocRespOfUpload {
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	domain := ReadDomain(rctx.Ctx)
+	isDuplicate := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		if override == common.Abort && isDuplicate {
+			openlog.Info(fmt.Sprintf("stop overriding kvs after reaching the duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+			appendFailedKVResult(config.ErrStopUpload, "stop overriding kvs after reaching the duplicate kv", kv, result)
+			continue
+		}
+		kv.Domain = domain
+		kv.Project = project
+		if kv.Status == "" {
+			kv.Status = common.StatusDisabled
+		}
+		err := validator.Validate(kv)
+		if err != nil {
+			appendFailedKVResult(config.ErrInvalidParams, err.Error(), kv, result)
+			continue
+		}
+		inputKV := kv
+		errCode, err := postOneKv(rctx, kv)
+		if errCode == config.ErrRecordAlreadyExists {
+			isDuplicate = true
+			strategyOfDuplicate(kv, result, rctx)
+			continue
+		}
+		if err != nil {
+			appendFailedKVResult(errCode, err.Error(), inputKV, result)
+			continue
+		}
+		checkKvChangeEvent(kv)
+		result.Success = append(result.Success, kv)
+	}
+	return result
+}
+
+func getKvByOptions(rctx *restful.Context, kv *model.KVDoc) (int32, error, []*model.KVDoc) {
+	request := &model.ListKVRequest{
+		Project: kv.Project,
+		Domain:  kv.Domain,
+		Key:     kv.Key,
+		Labels:  kv.Labels,
+	}
+	code, err, _, kvsDoc := queryListByOpts(rctx, request)
+	if err != nil {
+		return code, err, nil
+	}
+	return 0, nil, kvsDoc.Data
+}
+
+func strategyOfDuplicate(kv *model.KVDoc, result *model.DocRespOfUpload, rctx *restful.Context) {
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	if override == common.Skip {
+		openlog.Info(fmt.Sprintf("skip overriding duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+		appendFailedKVResult(config.ErrSkipDuplicateKV, "skip overriding duplicate kvs", kv, result)
+	} else if override == common.Abort {
+		openlog.Info(fmt.Sprintf("stop overriding duplicate [key: %s, labels: %s]", kv.Key, kv.Labels))
+		appendFailedKVResult(config.ErrRecordAlreadyExists, "stop overriding duplicate kv", kv, result)
+	} else {
+		errCode, err, getKvsByOpts := getKvByOptions(rctx, kv)
+		if err != nil {
+			openlog.Info(fmt.Sprintf("get record [key: %s, labels: %s] failed", kv.Key, kv.Labels))
+			appendFailedKVResult(errCode, err.Error(), kv, result)
+			return
+		}
+		kvReq := &model.UpdateKVRequest{
+			ID:      getKvsByOpts[0].ID,
+			Value:   kv.Value,
+			Domain:  kv.Domain,
+			Project: kv.Project,
+			Status:  kv.Status,
+		}
+		kvNew, err := service.KVService.Update(rctx.Ctx, kvReq)
+		if err != nil {
+			openlog.Error(fmt.Sprintf("update record [key: %s, labels: %s] failed", kv.Key, kv.Labels))
+			appendFailedKVResult(config.ErrInternal, err.Error(), kv, result)
+			return
+		}
+		checkKvChangeEvent(kvNew)
+		result.Success = append(result.Success, kvNew)
+	}
+}
+
+func appendFailedKVResult(errCode int32, errMsg string, kv *model.KVDoc, result *model.DocRespOfUpload) {

Review comment:
       done

##########
File path: server/resource/v1/common.go
##########
@@ -248,6 +248,20 @@ func checkDomainAndProject(domain, project string) error {
 }
 
 func queryAndResponse(rctx *restful.Context, request *model.ListKVRequest) {
+	errCode, err, rev, kv := queryListByOpts(rctx, request)
+	if err != nil {
+		WriteErrResponse(rctx, errCode, err.Error())
+		return
+	}
+	rctx.ReadResponseWriter().Header().Set(common.HeaderRevision, strconv.FormatInt(rev, 10))
+	err = writeResponse(rctx, kv)
+	rctx.ReadRestfulRequest().SetAttribute(common.RespBodyContextKey, kv.Data)
+	if err != nil {
+		openlog.Error(err.Error())
+	}
+}
+
+func queryListByOpts(rctx *restful.Context, request *model.ListKVRequest) (int32, error, int64, *model.KVResponse) {

Review comment:
       done

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +40,130 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	kvs := make([]*model.KVDoc, 0)
+	if err = readRequest(rctx, &kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	result := logicOfOverride(kvs[:], rctx)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661158280



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,6 +41,108 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	project := rctx.ReadPathParameter(common.PathParameterProject)
+	kvs := new([]*model.KVDoc)
+	if err = readRequest(rctx, kvs); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	overridden := rctx.ReadQueryParameter(common.QueryParamOverridden)
+	stopped := false
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	for _, kv := range *kvs {
+		if kv == nil {

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661938622



##########
File path: server/service/service.go
##########
@@ -82,5 +85,19 @@ type View interface {
 	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
 }
 
+var overrideMap = make(map[string]StrategyOverride)
+
+type StrategyOverride interface {
+	Execute(input *model.KVDoc, rctx *restful.Context, isDuplicate bool) (*model.KVDoc, *errsvc.Error)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661440593



##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,148 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	factory := new(OverrideType)

Review comment:
       done
   

##########
File path: server/resource/v1/kv_resource.go
##########
@@ -40,64 +41,148 @@ import (
 type KVResource struct {
 }
 
+//Upload upload kvs
+func (r *KVResource) Upload(rctx *restful.Context) {
+	var err error
+	inputUpload := new(KVUploadBody)
+	if err = readRequest(rctx, &inputUpload); err != nil {
+		WriteErrResponse(rctx, config.ErrInvalidParams, fmt.Sprintf(FmtReadRequestError, err))
+		return
+	}
+	kvs := inputUpload.Data
+	result := &model.DocRespOfUpload{
+		Success: []*model.KVDoc{},
+		Failure: []*model.DocFailedOfUpload{},
+	}
+	override := rctx.ReadQueryParameter(common.QueryParamOverride)
+	factory := new(OverrideType)
+	strategy := factory.getType(override)
+	isDuplicate := false
+	for _, kv := range kvs {
+		if kv == nil {
+			continue
+		}
+		kv, err0 := strategy.Execute(kv, rctx, isDuplicate)

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [servicecomb-kie] Sphairis commented on a change in pull request #185: add upload interface

Posted by GitBox <gi...@apache.org>.
Sphairis commented on a change in pull request #185:
URL: https://github.com/apache/servicecomb-kie/pull/185#discussion_r661363597



##########
File path: server/resource/v1/override_strategy.go
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/go-chassis/cari/pkg/errsvc"
+	"github.com/go-chassis/go-chassis/v2/server/restful"
+)
+
+var overrideMap = make(map[string]strategyOverride)
+
+func init() {
+	Register()
+}
+
+type OverrideType struct {
+}
+
+type strategyOverride interface {

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@servicecomb.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org