You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2022/01/04 09:50:29 UTC

[servicecomb-service-center] branch master updated: [feat] add microservice sync func and ut when db mode is etcd (#1202)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 9efc568  [feat] add microservice sync func and ut when db mode is etcd (#1202)
9efc568 is described below

commit 9efc56892c23668fc62de911a029758fd1b1ce00
Author: robotljw <79...@qq.com>
AuthorDate: Tue Jan 4 17:50:23 2022 +0800

    [feat] add microservice sync func and ut when db mode is etcd (#1202)
---
 datasource/common.go       |   1 +
 datasource/etcd/ms.go      |  53 +++++++++++++++--
 datasource/etcd/ms_test.go | 144 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 194 insertions(+), 4 deletions(-)

diff --git a/datasource/common.go b/datasource/common.go
index d391864..a3b9453 100644
--- a/datasource/common.go
+++ b/datasource/common.go
@@ -35,6 +35,7 @@ const (
 	ResourceAccount    = "account"
 	ResourceRole       = "role"
 	ResourceDependency = "dependency"
+	ResourceService    = "service"
 )
 
 // WrapErrResponse is temp func here to wait finish to refact the discosvc pkg
diff --git a/datasource/etcd/ms.go b/datasource/etcd/ms.go
index b3a24c4..2747834 100644
--- a/datasource/etcd/ms.go
+++ b/datasource/etcd/ms.go
@@ -25,6 +25,8 @@ import (
 	"strconv"
 	"time"
 
+	"github.com/go-chassis/cari/sync"
+
 	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/datasource/etcd/cache"
 	"github.com/apache/servicecomb-service-center/datasource/etcd/path"
@@ -125,6 +127,19 @@ func (ds *MetadataManager) RegisterService(ctx context.Context, request *pb.Crea
 		failOpts = append(failOpts, etcdadpt.OpGet(etcdadpt.WithStrKey(alias)))
 	}
 
+	if datasource.EnableSync {
+		domain := util.ParseDomain(ctx)
+		project := util.ParseProject(ctx)
+		taskOpt, err := GenTaskOpts(domain, project, sync.CreateAction, datasource.ResourceService, request)
+		if err != nil {
+			log.Error("fail to create task", err)
+			return &pb.CreateServiceResponse{
+				Response: pb.CreateResponse(pb.ErrInternal, err.Error()),
+			}, err
+		}
+		opts = append(opts, taskOpt)
+	}
+
 	resp, err := etcdadpt.TxnWithCmp(ctx, opts, uniqueCmpOpts, failOpts)
 	if err != nil {
 		log.Error(fmt.Sprintf("create micro-service[%s] failed, operator: %s",
@@ -472,11 +487,24 @@ func (ds *MetadataManager) UpdateService(ctx context.Context, request *pb.Update
 		}, err
 	}
 
+	opts := []etcdadpt.OpOptions{
+		etcdadpt.OpPut(etcdadpt.WithStrKey(key), etcdadpt.WithValue(data)),
+	}
+	if datasource.EnableSync {
+		domain := util.ParseDomain(ctx)
+		project := util.ParseProject(ctx)
+		taskOpt, err := GenTaskOpts(domain, project, sync.UpdateAction, datasource.ResourceService, request)
+		if err != nil {
+			log.Error("fail to create task", err)
+			return &pb.UpdateServicePropsResponse{
+				Response: pb.CreateResponse(pb.ErrInternal, err.Error()),
+			}, err
+		}
+		opts = append(opts, taskOpt)
+	}
+
 	// Set key file
-	resp, err := etcdadpt.TxnWithCmp(ctx,
-		etcdadpt.Ops(etcdadpt.OpPut(etcdadpt.WithStrKey(key), etcdadpt.WithValue(data))),
-		etcdadpt.If(etcdadpt.NotEqualVer(key, 0)),
-		nil)
+	resp, err := etcdadpt.TxnWithCmp(ctx, opts, etcdadpt.If(etcdadpt.NotEqualVer(key, 0)), nil)
 	if err != nil {
 		log.Error(fmt.Sprintf("update service[%s] properties failed, operator: %s", request.ServiceId, remoteIP), err)
 		return &pb.UpdateServicePropsResponse{
@@ -2015,6 +2043,23 @@ func (ds *MetadataManager) DeleteServicePri(ctx context.Context, serviceID strin
 		etcdadpt.OpDel(etcdadpt.WithStrKey(serviceIDKey)),
 	}
 
+	if datasource.EnableSync {
+		domain := util.ParseDomain(ctx)
+		project := util.ParseProject(ctx)
+		taskOpt, err := GenTaskOpts(domain, project, sync.DeleteAction, datasource.ResourceService,
+			&pb.DeleteServiceRequest{ServiceId: serviceID, Force: force})
+		if err != nil {
+			log.Error("fail to create task", err)
+			return pb.CreateResponse(pb.ErrInternal, err.Error()), err
+		}
+		tombstoneOpt, err := GenTombstoneOpts(domain, project, datasource.ResourceService, serviceID)
+		if err != nil {
+			log.Error("fail to create tombstone", err)
+			return pb.CreateResponse(pb.ErrInternal, err.Error()), err
+		}
+		opts = append(opts, taskOpt, tombstoneOpt)
+	}
+
 	//删除依赖规则
 	optDeleteDep, err := serviceUtil.DeleteDependencyForDeleteService(domainProject, serviceID, serviceKey)
 	if err != nil {
diff --git a/datasource/etcd/ms_test.go b/datasource/etcd/ms_test.go
new file mode 100644
index 0000000..4c2ba35
--- /dev/null
+++ b/datasource/etcd/ms_test.go
@@ -0,0 +1,144 @@
+/*
+ * 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 request 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 request 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 etcd_test
+
+import (
+	"context"
+	"testing"
+
+	pb "github.com/go-chassis/cari/discovery"
+	"github.com/go-chassis/cari/sync"
+	"github.com/stretchr/testify/assert"
+
+	"github.com/apache/servicecomb-service-center/datasource"
+	"github.com/apache/servicecomb-service-center/eventbase/model"
+	"github.com/apache/servicecomb-service-center/eventbase/service/task"
+	"github.com/apache/servicecomb-service-center/eventbase/service/tombstone"
+	"github.com/apache/servicecomb-service-center/pkg/util"
+)
+
+func microServiceGetContext() context.Context {
+	return util.WithNoCache(util.SetDomainProject(context.Background(), "sync-micro-service",
+		"sync-micro-service"))
+}
+
+func TestSyncMicroService(t *testing.T) {
+	datasource.EnableSync = true
+
+	var serviceID string
+
+	t.Run("register micro-service", func(t *testing.T) {
+		t.Run("register a micro service will create a task should pass", func(t *testing.T) {
+			resp, err := datasource.GetMetadataManager().RegisterService(microServiceGetContext(), &pb.CreateServiceRequest{
+				Service: &pb.MicroService{
+					AppId:       "sync_micro_service_group",
+					ServiceName: "sync_micro_service",
+					Version:     "1.0.0",
+					Level:       "FRONT",
+					Status:      pb.MS_UP,
+				},
+			})
+			assert.NotNil(t, resp)
+			assert.NoError(t, err)
+			assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+			serviceID = resp.ServiceId
+			listTaskReq := model.ListTaskRequest{
+				Domain:       "sync-micro-service",
+				Project:      "sync-micro-service",
+				ResourceType: datasource.ResourceService,
+				Action:       sync.CreateAction,
+				Status:       sync.PendingStatus,
+			}
+			tasks, err := task.List(context.Background(), &listTaskReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 1, len(tasks))
+			err = task.Delete(context.Background(), tasks...)
+			assert.NoError(t, err)
+			tasks, err = task.List(context.Background(), &listTaskReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 0, len(tasks))
+		})
+	})
+
+	t.Run("update micro-service", func(t *testing.T) {
+		t.Run("update a micro service setting sync-test property will create a task should pass", func(t *testing.T) {
+			request := &pb.UpdateServicePropsRequest{
+				ServiceId:  serviceID,
+				Properties: make(map[string]string),
+			}
+			request.Properties["sync-test"] = "sync-test"
+			resp, err := datasource.GetMetadataManager().UpdateService(microServiceGetContext(), request)
+			assert.NoError(t, err)
+			assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+			listTaskReq := model.ListTaskRequest{
+				Domain:       "sync-micro-service",
+				Project:      "sync-micro-service",
+				ResourceType: datasource.ResourceService,
+				Action:       sync.UpdateAction,
+				Status:       sync.PendingStatus,
+			}
+			tasks, err := task.List(context.Background(), &listTaskReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 1, len(tasks))
+			err = task.Delete(context.Background(), tasks...)
+			assert.NoError(t, err)
+			tasks, err = task.List(context.Background(), &listTaskReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 0, len(tasks))
+		})
+	})
+
+	t.Run("unregister micro-service", func(t *testing.T) {
+		t.Run("unregister a micro service will create a task and a tombstone should pass", func(t *testing.T) {
+			resp, err := datasource.GetMetadataManager().UnregisterService(microServiceGetContext(), &pb.DeleteServiceRequest{
+				ServiceId: serviceID,
+				Force:     true,
+			})
+			assert.NotNil(t, resp)
+			assert.NoError(t, err)
+			assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+			listTaskReq := model.ListTaskRequest{
+				Domain:       "sync-micro-service",
+				Project:      "sync-micro-service",
+				ResourceType: datasource.ResourceService,
+				Action:       sync.DeleteAction,
+				Status:       sync.PendingStatus,
+			}
+			tasks, err := task.List(context.Background(), &listTaskReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 1, len(tasks))
+			err = task.Delete(context.Background(), tasks...)
+			assert.NoError(t, err)
+			tasks, err = task.List(context.Background(), &listTaskReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 0, len(tasks))
+			tombstoneListReq := model.ListTombstoneRequest{
+				Domain:       "sync-micro-service",
+				Project:      "sync-micro-service",
+				ResourceType: datasource.ResourceService,
+			}
+			tombstones, err := tombstone.List(context.Background(), &tombstoneListReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 1, len(tombstones))
+			err = tombstone.Delete(context.Background(), tombstones...)
+			assert.NoError(t, err)
+		})
+	})
+
+	datasource.EnableSync = false
+}