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 2020/11/22 14:08:34 UTC

[GitHub] [servicecomb-service-center] little-cui commented on a change in pull request #752: SCB-2094 implement basic service/rule/schema/tag interface

little-cui commented on a change in pull request #752:
URL: https://github.com/apache/servicecomb-service-center/pull/752#discussion_r528340065



##########
File path: datasource/mongo/util.go
##########
@@ -0,0 +1,130 @@
+/*
+ * 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 mongo
+
+import (
+	"context"
+	"github.com/apache/servicecomb-service-center/datasource/mongo/client"
+	pb "github.com/apache/servicecomb-service-center/pkg/registry"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo/options"
+)
+
+func schemasAnalysis(schemas []*pb.Schema, schemasFromDb []*pb.Schema, schemaIDsInService []string) (
+	[]*pb.Schema, []*pb.Schema, []*pb.Schema, []string) {
+	needUpdateSchemas := make([]*pb.Schema, 0, len(schemas))
+	needAddSchemas := make([]*pb.Schema, 0, len(schemas))
+	needDeleteSchemas := make([]*pb.Schema, 0, len(schemasFromDb))
+	nonExistSchemaIds := make([]string, 0, len(schemas))
+
+	duplicate := make(map[string]struct{})
+	for _, schema := range schemas {
+		if _, ok := duplicate[schema.SchemaId]; ok {
+			continue
+		}
+		duplicate[schema.SchemaId] = struct{}{}
+
+		exist := false
+		for _, schemaFromDb := range schemasFromDb {
+			if schema.SchemaId == schemaFromDb.SchemaId {
+				needUpdateSchemas = append(needUpdateSchemas, schema)
+				exist = true
+				break
+			}
+		}
+		if !exist {
+			needAddSchemas = append(needAddSchemas, schema)
+		}
+
+		exist = false
+		for _, schemaID := range schemaIDsInService {
+			if schema.SchemaId == schemaID {
+				exist = true
+			}
+		}
+		if !exist {
+			nonExistSchemaIds = append(nonExistSchemaIds, schema.SchemaId)
+		}
+	}
+
+	for _, schemaFromDb := range schemasFromDb {
+		exist := false
+		for _, schema := range schemas {
+			if schema.SchemaId == schemaFromDb.SchemaId {
+				exist = true
+				break
+			}
+		}
+		if !exist {
+			needDeleteSchemas = append(needDeleteSchemas, schemaFromDb)
+		}
+	}
+
+	return needUpdateSchemas, needAddSchemas, needDeleteSchemas, nonExistSchemaIds
+}
+
+func SetServiceDefaultValue(service *pb.MicroService) {
+	if len(service.AppId) == 0 {
+		service.AppId = pb.AppID
+	}
+	if len(service.Version) == 0 {
+		service.Version = pb.VERSION
+	}
+	if len(service.Level) == 0 {
+		service.Level = "BACK"
+	}
+	if len(service.Status) == 0 {
+		service.Status = pb.MS_UP
+	}
+}
+
+func DocExist(ctx context.Context, table string, filter bson.M) (bool, error) {

Review comment:
       Should move these 4 funcs into mongo client pkg

##########
File path: datasource/mongo/config.go
##########
@@ -0,0 +1 @@
+package mongo

Review comment:
       Add Apache license header

##########
File path: datasource/mongo/ms.go
##########
@@ -19,164 +19,1433 @@ package mongo
 
 import (
 	"context"
+	"errors"
+	"fmt"
+	serviceUtil "github.com/apache/servicecomb-service-center/datasource/etcd/util"
+	"github.com/apache/servicecomb-service-center/datasource/mongo/client"
 	"github.com/apache/servicecomb-service-center/datasource/mongo/heartbeat"
+	"github.com/apache/servicecomb-service-center/pkg/log"
 	pb "github.com/apache/servicecomb-service-center/pkg/registry"
+	"github.com/apache/servicecomb-service-center/pkg/util"
+	apt "github.com/apache/servicecomb-service-center/server/core"
+	"github.com/apache/servicecomb-service-center/server/plugin/uuid"
+	scerr "github.com/apache/servicecomb-service-center/server/scerror"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo"
+	"go.mongodb.org/mongo-driver/mongo/options"
+	"strconv"
+	"time"
 )
 
 func (ds *DataSource) RegisterService(ctx context.Context, request *pb.CreateServiceRequest) (
 	*pb.CreateServiceResponse, error) {
-	return &pb.CreateServiceResponse{}, nil
-}
+	service := request.Service
+	serviceUtil.SetServiceDefaultValue(service)
 
-func (ds *DataSource) GetServices(ctx context.Context, request *pb.GetServicesRequest) (*pb.GetServicesResponse, error) {
-	return &pb.GetServicesResponse{}, nil
-}
+	domain := util.ParseDomain(ctx)
+	project := util.ParseProject(ctx)
+	//todo add quota check
+	requestServiceID := service.ServiceId
 
-func (ds *DataSource) GetService(ctx context.Context, request *pb.GetServiceRequest) (*pb.GetServiceResponse, error) {
-	return &pb.GetServiceResponse{}, nil
-}
+	if len(requestServiceID) == 0 {
+		ctx = util.SetContext(ctx, uuid.ContextKey, util.StringJoin([]string{domain, project, service.Environment, service.AppId, service.ServiceName, service.Alias, service.Version}, "/"))
+		service.ServiceId = uuid.Generator().GetServiceID(ctx)
+	}
+	// the service unique index in table is (serviceId,serviceEnv,serviceAppid,servicename,serviceAlias,serviceVersion)
+	existID, err := ServiceExistID(ctx, service.ServiceId)
+	if err != nil {
+		return &pb.CreateServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "Check service exist failed"),
+		}, err
+	}
+	exist, err := ServiceExist(ctx, &pb.MicroServiceKey{
+		Environment: service.Environment,
+		AppId:       service.AppId,
+		ServiceName: service.ServiceName,
+		Alias:       service.Alias,
+		Version:     service.Version,
+	})
+	if err != nil {
+		return &pb.CreateServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "Check service exist failed"),
+		}, err
+	}
+	if existID || exist {
+		return &pb.CreateServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrServiceAlreadyExists, "ServiceID conflict or found the same service."),
+		}, nil
+	}
+	insertRes, err := client.GetMongoClient().Insert(ctx, CollectionService, &MgService{Domain: domain, Project: project, Service: service})
+	if err != nil {
+		switch tt := err.(type) {
+		case mongo.WriteException:
+			if tt.WriteConcernError != nil {
+				for _, writeError := range tt.WriteErrors {
+					if writeError.Code == ErrorDuplicateKey {
+						return &pb.CreateServiceResponse{
+							Response: pb.CreateResponse(scerr.ErrServiceAlreadyExists, "ServiceID or ServiceInfo conflict."),
+						}, nil
+					}
+				}
+			}
+		default:
+			return &pb.CreateServiceResponse{
+				Response: pb.CreateResponse(scerr.ErrInternal, "Register service failed."),
+			}, err
+		}
+	}
 
-func (ds *DataSource) GetServiceDetail(ctx context.Context, request *pb.GetServiceRequest) (*pb.GetServiceDetailResponse, error) {
-	return &pb.GetServiceDetailResponse{}, nil
+	remoteIP := util.GetIPFromContext(ctx)
+	log.Infof("create micro-service[%s][%s] successfully,operator: %s", service.ServiceId, insertRes.InsertedID, remoteIP)
+
+	return &pb.CreateServiceResponse{
+		Response:  pb.CreateResponse(pb.ResponseSuccess, "Register service successfully"),
+		ServiceId: service.ServiceId,
+	}, nil
 }
 
-func (ds *DataSource) GetServicesInfo(ctx context.Context, request *pb.GetServicesInfoRequest) (*pb.GetServicesInfoResponse, error) {
-	return &pb.GetServicesInfoResponse{}, nil
+func (ds *DataSource) GetServices(ctx context.Context, request *pb.GetServicesRequest) (
+	*pb.GetServicesResponse, error) {
+
+	domain := util.ParseDomain(ctx)
+	project := util.ParseProject(ctx)
+
+	filter := bson.M{Domain: domain, Project: project}
+
+	services, err := GetServices(ctx, filter)
+	if err != nil {
+		return &pb.GetServicesResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "get services data failed."),
+		}, nil
+	}
+
+	return &pb.GetServicesResponse{
+		Response: pb.CreateResponse(pb.ResponseSuccess, "Get all services successfully."),
+		Services: services,
+	}, nil
 }
 
 func (ds *DataSource) GetApplications(ctx context.Context, request *pb.GetAppsRequest) (*pb.GetAppsResponse, error) {
-	return &pb.GetAppsResponse{}, nil
+	domain := util.ParseDomain(ctx)
+	project := util.ParseProject(ctx)
+
+	filter := bson.M{Domain: domain, Project: project, ServiceEnv: request.Environment}
+
+	services, err := GetServices(ctx, filter)
+	if err != nil {
+		return &pb.GetAppsResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "get services data failed."),
+		}, nil
+	}
+	l := len(services)
+	if l == 0 {
+		return &pb.GetAppsResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "get services data failed."),
+		}, nil
+	}
+	apps := make([]string, 0, l)
+	hash := make(map[string]struct{}, l)
+	for _, svc := range services {
+		if !request.WithShared && apt.IsGlobal(pb.MicroServiceToKey(util.ParseDomainProject(ctx), svc)) {
+			continue
+		}
+		if _, ok := hash[svc.AppId]; ok {
+			continue
+		}
+		hash[svc.AppId] = struct{}{}
+		apps = append(apps, svc.AppId)
+	}
+	return &pb.GetAppsResponse{
+		Response: pb.CreateResponse(pb.ResponseSuccess, "Get all applications successfully."),
+		AppIds:   apps,
+	}, nil
+}
+
+func (ds *DataSource) GetService(ctx context.Context, request *pb.GetServiceRequest) (
+	*pb.GetServiceResponse, error) {
+	svc, err := GetService(ctx, GeneratorServiceFilter(ctx, request.ServiceId))
+	if err != nil {
+		log.Errorf(err, "failed to get single service [%s] from mongo", request.ServiceId)
+		return &pb.GetServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "get service data from mongodb failed."),
+		}, err
+	}
+	if svc != nil {
+		return &pb.GetServiceResponse{
+			Response: pb.CreateResponse(pb.ResponseSuccess, "Get service successfully."),
+			Service:  svc.Service,
+		}, nil
+	}
+	return &pb.GetServiceResponse{
+		Response: pb.CreateResponse(scerr.ErrServiceNotExists, "Service not exist."),
+	}, nil
 }
 
 func (ds *DataSource) ExistServiceByID(ctx context.Context, request *pb.GetExistenceByIDRequest) (*pb.GetExistenceByIDResponse, error) {
-	return &pb.GetExistenceByIDResponse{}, nil
+
+	exist, err := ServiceExistID(ctx, request.ServiceId)
+	if err != nil {
+		return &pb.GetExistenceByIDResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "Check service exist failed."),
+			Exist:    false,
+		}, err
+	}
+
+	return &pb.GetExistenceByIDResponse{
+		Response: pb.CreateResponse(pb.ResponseSuccess, "Check ExistService successfully."),
+		Exist:    exist,
+	}, nil
 }
 
 func (ds *DataSource) ExistService(ctx context.Context, request *pb.GetExistenceRequest) (*pb.GetExistenceResponse, error) {
-	return &pb.GetExistenceResponse{}, nil
+	serviceKey := &pb.MicroServiceKey{
+		Environment: request.Environment,
+		AppId:       request.AppId,
+		ServiceName: request.ServiceName,
+		Alias:       request.ServiceName,
+		Version:     request.Version,
+	}
+	//todo add verison match.
+	services, err := GetServices(ctx, GeneratorServiceNameFilter(ctx, serviceKey))
+	if err != nil {
+		return &pb.GetExistenceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, err.Error()),
+		}, err
+	}
+	if len(services) != 0 {
+		return &pb.GetExistenceResponse{
+			Response:  pb.CreateResponse(pb.ResponseSuccess, "get service id successfully."),
+			ServiceId: services[0].ServiceId,
+		}, nil
+	}
+	services, err = GetServices(ctx, GeneratorServiceAliasFilter(ctx, serviceKey))
+	if err != nil {
+		return &pb.GetExistenceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, err.Error()),
+		}, err
+	}
+	if len(services) != 0 {
+		return &pb.GetExistenceResponse{
+			Response:  pb.CreateResponse(pb.ResponseSuccess, "get service id successfully."),
+			ServiceId: services[0].ServiceId,
+		}, nil
+	}
+	return &pb.GetExistenceResponse{
+		Response: pb.CreateResponse(scerr.ErrServiceNotExists, "Service does not exist"),
+	}, nil
 }
 
-func (ds *DataSource) UpdateService(ctx context.Context, request *pb.UpdateServicePropsRequest) (*pb.UpdateServicePropsResponse, error) {
-	return &pb.UpdateServicePropsResponse{}, nil
+func (ds *DataSource) UnregisterService(ctx context.Context, request *pb.DeleteServiceRequest) (*pb.DeleteServiceResponse, error) {
+	exist, err := ServiceExistID(ctx, request.ServiceId)
+	if err != nil {
+		return &pb.DeleteServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "Delete service failed,failed to get service."),
+		}, err
+	}
+	if !exist {
+		return &pb.DeleteServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrServiceNotExists, "Delete service failed,service not exist."),
+		}, nil
+	}
+	session, err := client.GetMongoClient().StartSession(ctx)
+	if err != nil {
+		return &pb.DeleteServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "DelService failed to create session."),
+		}, err
+	}
+	if err = session.StartTransaction(); err != nil {
+		return &pb.DeleteServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "DelService failed to start session."),
+		}, err
+	}
+	defer session.EndSession(ctx)
+	//todo delete instance,tags,schemas...
+	res, err := DelServicePri(ctx, request.ServiceId, request.Force)
+	if err != nil {
+		errAbort := session.AbortTransaction(ctx)
+		if errAbort != nil {
+			return &pb.DeleteServiceResponse{
+				Response: pb.CreateResponse(scerr.ErrInternal, "Txn delete service abort failed."),
+			}, errAbort
+		}
+		return &pb.DeleteServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "Delete service failed"),
+		}, err
+	}
+	errCommit := session.CommitTransaction(ctx)
+	if errCommit != nil {
+		return &pb.DeleteServiceResponse{
+			Response: pb.CreateResponse(scerr.ErrInternal, "Txn delete service commit failed."),
+		}, errCommit
+	}
+	//_, err := client.GetMongoClient().DeleteOne(ctx, CollectionService, GeneratorServiceFilter(ctx, request.ServiceId))

Review comment:
       why not remove these comments




----------------------------------------------------------------
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