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 0d24f08  fix dep rule (#830)
0d24f08 is described below

commit 0d24f08c7dcd700c9f015db9f8bb0615af111ba0
Author: xzccfzy <[email protected]>
AuthorDate: Tue Jan 19 10:24:46 2021 +0800

    fix dep rule (#830)
---
 datasource/dependency_util.go        | 138 ++++++++++++-
 datasource/mongo/client/mongo.go     |   2 +-
 datasource/mongo/database.go         |  33 +++-
 datasource/mongo/dep.go              | 370 +++++++++++++++++++++++++++++++----
 datasource/mongo/dep_test.go         | 102 +++++-----
 datasource/mongo/dependency_query.go | 336 ++++++++++++++++++++++++-------
 datasource/mongo/mongo_suite_test.go |   4 +
 datasource/mongo/ms.go               | 144 ++++++++++++--
 datasource/mongo/sd/types.go         |   8 +-
 9 files changed, 941 insertions(+), 196 deletions(-)

diff --git a/datasource/dependency_util.go b/datasource/dependency_util.go
index c907f04..d166119 100644
--- a/datasource/dependency_util.go
+++ b/datasource/dependency_util.go
@@ -1,12 +1,27 @@
 package datasource
 
 import (
+       "context"
+       "errors"
+       "fmt"
+       "strings"
+
        "github.com/apache/servicecomb-service-center/datasource/etcd/path"
        "github.com/apache/servicecomb-service-center/pkg/log"
-       pb "github.com/go-chassis/cari/discovery"
+       "github.com/go-chassis/cari/discovery"
 )
 
-func ParamsChecker(consumerInfo *pb.MicroServiceKey, providersInfo 
[]*pb.MicroServiceKey) *pb.CreateDependenciesResponse {
+type Dependency struct {
+       DomainProject string
+       // store the consumer Dependency from dep-queue object
+       Consumer      *discovery.MicroServiceKey
+       ProvidersRule []*discovery.MicroServiceKey
+       // store the parsed rules from Dependency object
+       DeleteDependencyRuleList []*discovery.MicroServiceKey
+       CreateDependencyRuleList []*discovery.MicroServiceKey
+}
+
+func ParamsChecker(consumerInfo *discovery.MicroServiceKey, providersInfo 
[]*discovery.MicroServiceKey) *discovery.CreateDependenciesResponse {
        flag := make(map[string]bool, len(providersInfo))
        for _, providerInfo := range providersInfo {
                //存在带*的情况,后面的数据就不校验了
@@ -32,16 +47,125 @@ func ParamsChecker(consumerInfo *pb.MicroServiceKey, 
providersInfo []*pb.MicroSe
        return nil
 }
 
-func BadParamsResponse(detailErr string) *pb.CreateDependenciesResponse {
-       log.Errorf(nil, "request params is invalid. %s", detailErr)
+func BadParamsResponse(detailErr string) *discovery.CreateDependenciesResponse 
{
+       log.Error(fmt.Sprintf("request params is invalid. %s", detailErr), nil)
        if len(detailErr) == 0 {
                detailErr = "Request params is invalid."
        }
-       return &pb.CreateDependenciesResponse{
-               Response: pb.CreateResponse(pb.ErrInvalidParams, detailErr),
+       return &discovery.CreateDependenciesResponse{
+               Response: discovery.CreateResponse(discovery.ErrInvalidParams, 
detailErr),
        }
 }
 
-func toString(in *pb.MicroServiceKey) string {
+func toString(in *discovery.MicroServiceKey) string {
        return path.GenerateProviderDependencyRuleKey(in.Tenant, in)
 }
+
+func ParseAddOrUpdateRules(ctx context.Context, dep *Dependency, 
oldProviderRules *discovery.MicroServiceDependency) {
+       deleteDependencyRuleList := make([]*discovery.MicroServiceKey, 0, 
len(oldProviderRules.Dependency))
+       createDependencyRuleList := make([]*discovery.MicroServiceKey, 0, 
len(dep.ProvidersRule))
+       existDependencyRuleList := make([]*discovery.MicroServiceKey, 0, 
len(oldProviderRules.Dependency))
+       for _, tmpProviderRule := range dep.ProvidersRule {
+               if ok, _ := 
ContainServiceDependency(oldProviderRules.Dependency, tmpProviderRule); ok {
+                       continue
+               }
+
+               if tmpProviderRule.ServiceName == "*" {
+                       createDependencyRuleList = 
append([]*discovery.MicroServiceKey{}, tmpProviderRule)
+                       deleteDependencyRuleList = oldProviderRules.Dependency
+                       break
+               }
+
+               createDependencyRuleList = append(createDependencyRuleList, 
tmpProviderRule)
+               old := IsNeedUpdate(oldProviderRules.Dependency, 
tmpProviderRule)
+               if old != nil {
+                       deleteDependencyRuleList = 
append(deleteDependencyRuleList, old)
+               }
+       }
+       for _, oldProviderRule := range oldProviderRules.Dependency {
+               if oldProviderRule.ServiceName == "*" {
+                       return
+               }
+               if ok, _ := ContainServiceDependency(deleteDependencyRuleList, 
oldProviderRule); !ok {
+                       existDependencyRuleList = 
append(existDependencyRuleList, oldProviderRule)
+               }
+       }
+
+       dep.ProvidersRule = append(createDependencyRuleList, 
existDependencyRuleList...)
+       setDep(dep, createDependencyRuleList, existDependencyRuleList, 
deleteDependencyRuleList)
+}
+
+func ParseOverrideRules(ctx context.Context, dep *Dependency, oldProviderRules 
*discovery.MicroServiceDependency) {
+       deleteDependencyRuleList := make([]*discovery.MicroServiceKey, 0, 
len(oldProviderRules.Dependency))
+       createDependencyRuleList := make([]*discovery.MicroServiceKey, 0, 
len(dep.ProvidersRule))
+       existDependencyRuleList := make([]*discovery.MicroServiceKey, 0, 
len(oldProviderRules.Dependency))
+       for _, oldProviderRule := range oldProviderRules.Dependency {
+               if ok, _ := ContainServiceDependency(dep.ProvidersRule, 
oldProviderRule); !ok {
+                       deleteDependencyRuleList = 
append(deleteDependencyRuleList, oldProviderRule)
+               } else {
+                       existDependencyRuleList = 
append(existDependencyRuleList, oldProviderRule)
+               }
+       }
+       for _, tmpProviderRule := range dep.ProvidersRule {
+               if ok, _ := ContainServiceDependency(existDependencyRuleList, 
tmpProviderRule); !ok {
+                       createDependencyRuleList = 
append(createDependencyRuleList, tmpProviderRule)
+               }
+       }
+       setDep(dep, createDependencyRuleList, existDependencyRuleList, 
deleteDependencyRuleList)
+}
+
+func setDep(dep *Dependency, createDependencyRuleList, 
existDependencyRuleList, deleteDependencyRuleList []*discovery.MicroServiceKey) 
{
+       consumerFlag := strings.Join([]string{dep.Consumer.Environment, 
dep.Consumer.AppId, dep.Consumer.ServiceName, dep.Consumer.Version}, "/")
+
+       if len(createDependencyRuleList) == 0 && len(existDependencyRuleList) 
== 0 && len(deleteDependencyRuleList) == 0 {
+               return
+       }
+
+       if len(deleteDependencyRuleList) != 0 {
+               log.Info(fmt.Sprintf("delete consumer[%s]'s dependency rule 
%v", consumerFlag, deleteDependencyRuleList))
+               dep.DeleteDependencyRuleList = deleteDependencyRuleList
+       }
+
+       if len(createDependencyRuleList) != 0 {
+               log.Info(fmt.Sprintf("create consumer[%s]'s dependency rule 
%v", consumerFlag, createDependencyRuleList))
+               dep.CreateDependencyRuleList = createDependencyRuleList
+       }
+}
+
+func ContainServiceDependency(services []*discovery.MicroServiceKey, service 
*discovery.MicroServiceKey) (bool, error) {
+       if services == nil || service == nil {
+               return false, errors.New("invalid params input")
+       }
+       for _, value := range services {
+               rst := EqualServiceDependency(service, value)
+               if rst {
+                       return true, nil
+               }
+       }
+       return false, nil
+}
+
+func EqualServiceDependency(serviceA *discovery.MicroServiceKey, serviceB 
*discovery.MicroServiceKey) bool {
+       stringA := toString(serviceA)
+       stringB := toString(serviceB)
+       return stringA == stringB
+}
+
+func IsNeedUpdate(services []*discovery.MicroServiceKey, service 
*discovery.MicroServiceKey) *discovery.MicroServiceKey {
+       for _, tmp := range services {
+               if DiffServiceVersion(tmp, service) {
+                       return tmp
+               }
+       }
+       return nil
+}
+
+func DiffServiceVersion(serviceA *discovery.MicroServiceKey, serviceB 
*discovery.MicroServiceKey) bool {
+       stringA := toString(serviceA)
+       stringB := toString(serviceB)
+       if stringA != stringB &&
+               stringA[:strings.LastIndex(stringA, "/")+1] == 
stringB[:strings.LastIndex(stringB, "/")+1] {
+               return true
+       }
+       return false
+}
diff --git a/datasource/mongo/client/mongo.go b/datasource/mongo/client/mongo.go
index aac7be7..f63c6a9 100644
--- a/datasource/mongo/client/mongo.go
+++ b/datasource/mongo/client/mongo.go
@@ -210,7 +210,7 @@ func (mc *MongoClient) MultiTableBatchUpdate(ctx 
context.Context, opts []MongoOp
        return nil
 }
 
-func (mc *MongoClient) DocExist(ctx context.Context, table string, filter 
bson.M) (bool, error) {
+func (mc *MongoClient) DocExist(ctx context.Context, table string, filter 
interface{}) (bool, error) {
        res, err := mc.FindOne(ctx, table, filter)
        if err != nil {
                return false, err
diff --git a/datasource/mongo/database.go b/datasource/mongo/database.go
index 465e19a..aa1b973 100644
--- a/datasource/mongo/database.go
+++ b/datasource/mongo/database.go
@@ -59,14 +59,18 @@ const (
        ColumnRuleType            = "ruletype"
        ColumnSchemaInfo          = "schemainfo"
        ColumnSchemaSummary       = "schemasummary"
-       ColumnConsumer            = "consumer"
-       ColumnDependencyInfo      = "dependencyinfo"
+       ColumnDepInfo             = "depinfo"
+       ColumnDependency          = "dependency"
        ColumnRuleInfo            = "ruleinfo"
        ColumnInstanceInfo        = "instanceinfo"
        ColumnInstanceID          = "instanceid"
        ColumnConsumerID          = "consumerid"
        ColumnMongoID             = "_id"
        ColumnTenant              = "tenant"
+       ColumnServiceType         = "type"
+       ColumnServiceKey          = "servicekey"
+       ColumnConsumer            = "consumer"
+       ColumnDependencyInfo      = "dependencyinfo"
        ColumnID                  = "id"
        ColumnAccountName         = "name"
        ColumnRoleName            = "name"
@@ -109,10 +113,23 @@ type Instance struct {
        InstanceInfo *pb.MicroServiceInstance
 }
 
-type Dependency struct {
-       Domain         string
-       Project        string
-       ConsumerID     string
-       UUID           string
-       DependencyInfo *pb.ConsumerDependency
+type ConsumerDep struct {
+       Domain          string
+       Project         string
+       ConsumerID      string
+       UUID            string
+       ConsumerDepInfo *pb.ConsumerDependency
+}
+
+type DependencyRule struct {
+       Type       string
+       Domain     string
+       Project    string
+       ServiceKey *pb.MicroServiceKey
+       DepInfo    *pb.MicroServiceDependency
+}
+
+type DelDepCacheKey struct {
+       key  *pb.MicroServiceKey
+       Type string
 }
diff --git a/datasource/mongo/dep.go b/datasource/mongo/dep.go
index c45577a..07634e6 100644
--- a/datasource/mongo/dep.go
+++ b/datasource/mongo/dep.go
@@ -22,16 +22,17 @@ import (
        "errors"
        "fmt"
 
-       pb "github.com/go-chassis/cari/discovery"
-       "go.mongodb.org/mongo-driver/bson"
-
        "github.com/apache/servicecomb-service-center/datasource"
+       "github.com/apache/servicecomb-service-center/datasource/etcd/path"
        "github.com/apache/servicecomb-service-center/datasource/mongo/client"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/util"
+       "github.com/go-chassis/cari/discovery"
+       "go.mongodb.org/mongo-driver/bson"
+       "go.mongodb.org/mongo-driver/mongo/options"
 )
 
-func (ds *DataSource) SearchProviderDependency(ctx context.Context, request 
*pb.GetDependenciesRequest) (*pb.GetProDependenciesResponse, error) {
+func (ds *DataSource) SearchProviderDependency(ctx context.Context, request 
*discovery.GetDependenciesRequest) (*discovery.GetProDependenciesResponse, 
error) {
        domainProject := util.ParseDomainProject(ctx)
        providerServiceID := request.ServiceId
        filter := GeneratorServiceFilter(ctx, providerServiceID)
@@ -39,31 +40,37 @@ func (ds *DataSource) SearchProviderDependency(ctx 
context.Context, request *pb.
        if err != nil {
                if errors.Is(err, datasource.ErrNoData) {
                        log.Debug(fmt.Sprintf("query provider service failed, 
there is no provider %s in db", providerServiceID))
-                       return &pb.GetProDependenciesResponse{
-                               Response: 
pb.CreateResponse(pb.ErrServiceNotExists, "Provider does not exist"),
+                       return &discovery.GetProDependenciesResponse{
+                               Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, "Provider does not 
exist"),
                        }, nil
                }
                log.Error(fmt.Sprintf("query provider from db error, provider 
is %s", providerServiceID), err)
                return nil, err
        }
+       if provider == nil {
+               log.Error(fmt.Sprintf("GetProviderDependencies failed for 
provider %s", providerServiceID), err)
+               return &discovery.GetProDependenciesResponse{
+                       Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, "Provider does not 
exist"),
+               }, nil
+       }
 
        dr := NewProviderDependencyRelation(ctx, domainProject, 
provider.ServiceInfo)
        services, err := 
dr.GetDependencyConsumers(ToDependencyFilterOptions(request)...)
        if err != nil {
                log.Error(fmt.Sprintf("GetProviderDependencies failed, provider 
is %s/%s/%s/%s",
                        provider.ServiceInfo.Environment, 
provider.ServiceInfo.AppId, provider.ServiceInfo.ServiceName, 
provider.ServiceInfo.Version), err)
-               return &pb.GetProDependenciesResponse{
-                       Response: pb.CreateResponse(pb.ErrInternal, 
err.Error()),
+               return &discovery.GetProDependenciesResponse{
+                       Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
        }
 
-       return &pb.GetProDependenciesResponse{
-               Response:  pb.CreateResponse(pb.ResponseSuccess, "Get all 
consumers successful."),
+       return &discovery.GetProDependenciesResponse{
+               Response:  discovery.CreateResponse(discovery.ResponseSuccess, 
"Get all consumers successful."),
                Consumers: services,
        }, nil
 }
 
-func (ds *DataSource) SearchConsumerDependency(ctx context.Context, request 
*pb.GetDependenciesRequest) (*pb.GetConDependenciesResponse, error) {
+func (ds *DataSource) SearchConsumerDependency(ctx context.Context, request 
*discovery.GetDependenciesRequest) (*discovery.GetConDependenciesResponse, 
error) {
        domainProject := util.ParseDomainProject(ctx)
        consumerID := request.ServiceId
 
@@ -72,31 +79,37 @@ func (ds *DataSource) SearchConsumerDependency(ctx 
context.Context, request *pb.
        if err != nil {
                if errors.Is(err, datasource.ErrNoData) {
                        log.Debug(fmt.Sprintf("query consumer service failed, 
there is no consumer %s in db", consumerID))
-                       return &pb.GetConDependenciesResponse{
-                               Response: 
pb.CreateResponse(pb.ErrServiceNotExists, "Consumer does not exist"),
+                       return &discovery.GetConDependenciesResponse{
+                               Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, "Consumer does not 
exist"),
                        }, nil
                }
                log.Error(fmt.Sprintf("query consumer from db error, consumer 
is %s", consumerID), err)
                return nil, err
        }
+       if consumer == nil {
+               log.Error(fmt.Sprintf("GetConsumerDependencies failed for 
consumer %s does not exist", consumerID), err)
+               return &discovery.GetConDependenciesResponse{
+                       Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, "Consumer does not 
exist"),
+               }, nil
+       }
 
        dr := NewConsumerDependencyRelation(ctx, domainProject, 
consumer.ServiceInfo)
        services, err := 
dr.GetDependencyProviders(ToDependencyFilterOptions(request)...)
        if err != nil {
                log.Error(fmt.Sprintf("query consumer failed, consumer is 
%s/%s/%s/%s",
                        consumer.ServiceInfo.Environment, 
consumer.ServiceInfo.AppId, consumer.ServiceInfo.ServiceName, 
consumer.ServiceInfo.Version), err)
-               return &pb.GetConDependenciesResponse{
-                       Response: pb.CreateResponse(pb.ErrInternal, 
err.Error()),
+               return &discovery.GetConDependenciesResponse{
+                       Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
        }
 
-       return &pb.GetConDependenciesResponse{
-               Response:  pb.CreateResponse(pb.ResponseSuccess, "get all 
providers successfully."),
+       return &discovery.GetConDependenciesResponse{
+               Response:  discovery.CreateResponse(discovery.ResponseSuccess, 
"Get all providers successfully."),
                Providers: services,
        }, nil
 }
 
-func (ds *DataSource) AddOrUpdateDependencies(ctx context.Context, 
dependencyInfos []*pb.ConsumerDependency, override bool) (*pb.Response, error) {
+func (ds *DataSource) AddOrUpdateDependencies(ctx context.Context, 
dependencyInfos []*discovery.ConsumerDependency, override bool) 
(*discovery.Response, error) {
        domainProject := util.ParseDomainProject(ctx)
        for _, dependencyInfo := range dependencyInfos {
                consumerFlag := util.StringJoin([]string{
@@ -104,8 +117,8 @@ func (ds *DataSource) AddOrUpdateDependencies(ctx 
context.Context, dependencyInf
                        dependencyInfo.Consumer.AppId,
                        dependencyInfo.Consumer.ServiceName,
                        dependencyInfo.Consumer.Version}, "/")
-               consumerInfo := 
pb.DependenciesToKeys([]*pb.MicroServiceKey{dependencyInfo.Consumer}, 
domainProject)[0]
-               providersInfo := 
pb.DependenciesToKeys(dependencyInfo.Providers, domainProject)
+               consumerInfo := 
discovery.DependenciesToKeys([]*discovery.MicroServiceKey{dependencyInfo.Consumer},
 domainProject)[0]
+               providersInfo := 
discovery.DependenciesToKeys(dependencyInfo.Providers, domainProject)
 
                rsp := datasource.ParamsChecker(consumerInfo, providersInfo)
                if rsp != nil {
@@ -118,44 +131,323 @@ func (ds *DataSource) AddOrUpdateDependencies(ctx 
context.Context, dependencyInf
                if err != nil && !errors.Is(err, datasource.ErrNoData) {
                        log.Error(fmt.Sprintf("put request into dependency 
queue failed, override: %t, get consumer %s id failed",
                                override, consumerFlag), err)
-                       return pb.CreateResponse(pb.ErrInternal, err.Error()), 
err
+                       return discovery.CreateResponse(discovery.ErrInternal, 
err.Error()), err
                }
                if len(consumerID) == 0 {
                        log.Error(fmt.Sprintf("put request into dependency 
queue failed, override: %t consumer %s does not exist",
                                override, consumerFlag), err)
-                       return pb.CreateResponse(pb.ErrServiceNotExists, 
fmt.Sprintf("Consumer %s does not exist.", consumerFlag)), nil
+                       return 
discovery.CreateResponse(discovery.ErrServiceNotExists, fmt.Sprintf("Consumer 
%s does not exist.", consumerFlag)), nil
                }
 
                dependencyInfo.Override = override
-               id := DepsQueueUUID
                if !override {
-                       id = util.GenerateUUID()
-               }
+                       id := util.GenerateUUID()
 
-               domain := util.ParseDomain(ctx)
-               project := util.ParseProject(ctx)
-               data := &Dependency{
-                       Domain:         domain,
-                       Project:        project,
-                       ConsumerID:     consumerID,
-                       UUID:           id,
-                       DependencyInfo: dependencyInfo,
+                       domain := util.ParseDomain(ctx)
+                       project := util.ParseProject(ctx)
+                       data := &ConsumerDep{
+                               Domain:          domain,
+                               Project:         project,
+                               ConsumerID:      consumerID,
+                               UUID:            id,
+                               ConsumerDepInfo: dependencyInfo,
+                       }
+                       insertRes, err := client.GetMongoClient().Insert(ctx, 
CollectionDep, data)
+                       if err != nil {
+                               log.Error("failed to insert dep to mongodb", 
err)
+                               return 
discovery.CreateResponse(discovery.ErrInternal, err.Error()), err
+                       }
+                       log.Info(fmt.Sprintf("insert dep to mongodb success 
%s", insertRes.InsertedID))
                }
-               insertRes, err := client.GetMongoClient().Insert(ctx, 
CollectionDep, data)
+               err = syncDependencyRule(ctx, domainProject, dependencyInfo)
                if err != nil {
-                       log.Error("failed to insert dep to mongodb", err)
-                       return pb.CreateResponse(pb.ErrInternal, err.Error()), 
err
+                       return nil, err
                }
-               log.Error(fmt.Sprintf("insert dep to mongodb success %s", 
insertRes.InsertedID), err)
        }
-       return pb.CreateResponse(pb.ResponseSuccess, "Create dependency 
successfully."), nil
+       return discovery.CreateResponse(discovery.ResponseSuccess, "Create 
dependency successfully."), nil
 }
 
 func (ds *DataSource) DeleteDependency() {
        panic("implement me")
 }
 
-func GetServiceID(ctx context.Context, key *pb.MicroServiceKey) (string, 
error) {
+func syncDependencyRule(ctx context.Context, domainProject string, r 
*discovery.ConsumerDependency) error {
+
+       consumerInfo := 
discovery.DependenciesToKeys([]*discovery.MicroServiceKey{r.Consumer}, 
domainProject)[0]
+       providersInfo := discovery.DependenciesToKeys(r.Providers, 
domainProject)
+
+       var dep datasource.Dependency
+       //var err error
+       dep.DomainProject = domainProject
+       dep.Consumer = consumerInfo
+       dep.ProvidersRule = providersInfo
+       // add mongo get dep here
+
+       oldProviderRules, err := GetOldProviderRules(&dep)
+       if err != nil {
+               return err
+       }
+
+       if r.Override {
+               datasource.ParseOverrideRules(ctx, &dep, oldProviderRules)
+       } else {
+               datasource.ParseAddOrUpdateRules(ctx, &dep, oldProviderRules)
+       }
+       return updateDeps(domainProject, &dep)
+}
+
+func GetOldProviderRules(dep *datasource.Dependency) 
(*discovery.MicroServiceDependency, error) {
+       microServiceDependency := &discovery.MicroServiceDependency{
+               Dependency: []*discovery.MicroServiceKey{},
+       }
+       filter := GenerateConsumerDependencyRuleKey(dep.DomainProject, 
dep.Consumer)
+       findRes, err := client.GetMongoClient().FindOne(context.TODO(), 
CollectionDep, filter)
+       if err != nil {
+               log.Error(fmt.Sprintf("get dependency rule [%v] failed", 
filter), err)
+               return nil, err
+       }
+
+       if findRes.Err() != nil {
+               return microServiceDependency, nil
+       }
+
+       var depRule *DependencyRule
+       err = findRes.Decode(&depRule)
+       if err != nil {
+               return nil, err
+       }
+       return depRule.DepInfo, nil
+}
+
+func updateDeps(domainProject string, dep *datasource.Dependency) error {
+       var upsert = true
+       for _, r := range dep.DeleteDependencyRuleList {
+               filter := GenerateProviderDependencyRuleKey(domainProject, r)
+               _, err := client.GetMongoClient().Update(context.TODO(), 
CollectionDep, filter, bson.M{"$pull": 
bson.M{StringBuilder([]string{ColumnDepInfo, ColumnDependency}): dep.Consumer}})
+               if err != nil {
+                       return err
+               }
+               if r.ServiceName == "*" {
+                       break
+               }
+       }
+       for _, r := range dep.CreateDependencyRuleList {
+               filter := GenerateProviderDependencyRuleKey(domainProject, r)
+               data := bson.M{
+                       "$addToSet": 
bson.M{StringBuilder([]string{ColumnDepInfo, ColumnDependency}): dep.Consumer},
+               }
+               _, err := client.GetMongoClient().Update(context.TODO(), 
CollectionDep, filter, data, &options.UpdateOptions{Upsert: &upsert})
+               if err != nil {
+                       return err
+               }
+               if r.ServiceName == "*" {
+                       break
+               }
+       }
+       filter := GenerateConsumerDependencyRuleKey(domainProject, dep.Consumer)
+       if len(dep.ProvidersRule) == 0 {
+               _, err := client.GetMongoClient().Delete(context.TODO(), 
CollectionDep, filter)
+               if err != nil {
+                       return err
+               }
+       } else {
+               updateData := bson.M{
+                       "$set": bson.M{StringBuilder([]string{ColumnDepInfo, 
ColumnDependency}): dep.ProvidersRule},
+               }
+               _, err := client.GetMongoClient().Update(context.TODO(), 
CollectionDep, filter, updateData, &options.UpdateOptions{Upsert: &upsert})
+               if err != nil {
+                       return err
+               }
+       }
+
+       err := CleanUpDepRules(context.TODO(), domainProject)
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+func CleanUpDepRules(ctx context.Context, domainProject string) error {
+       if len(domainProject) == 0 {
+               return ErrInvalidDomainProject
+       }
+
+       cache := make(map[*DelDepCacheKey]bool)
+       err := removeProviderRuleOfConsumer(ctx, domainProject, cache)
+
+       if err != nil {
+               return err
+       }
+
+       return removeProviderRuleKeys(ctx, domainProject, cache)
+}
+
+func removeProviderRuleOfConsumer(ctx context.Context, domainProject string, 
cache map[*DelDepCacheKey]bool) error {
+       filter := GenerateConsumerDependencyRuleKey(domainProject, nil)
+       depRules, err := GetDepRules(ctx, filter)
+       if err != nil {
+               return err
+       }
+       for _, depRule := range depRules {
+               err := removeConsumerDeps(ctx, depRule, cache)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func removeProviderRuleKeys(ctx context.Context, domainProject string, cache 
map[*DelDepCacheKey]bool) error {
+       filter := GenerateProviderDependencyRuleKey(domainProject, nil)
+       depRules, err := GetDepRules(ctx, filter)
+       if err != nil {
+               return err
+       }
+       for _, depRule := range depRules {
+               err := removeProviderDeps(ctx, depRule, cache)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func GetDepRules(ctx context.Context, filter bson.M) ([]*DependencyRule, 
error) {
+       findRes, err := client.GetMongoClient().Find(ctx, CollectionDep, filter)
+       if err != nil {
+               return nil, err
+       }
+
+       var depRules []*DependencyRule
+       for findRes.Next(ctx) {
+               var depRule *DependencyRule
+               err := findRes.Decode(&depRule)
+               if err != nil {
+                       return nil, err
+               }
+               depRules = append(depRules, depRule)
+       }
+       return depRules, nil
+}
+
+func removeProviderDeps(ctx context.Context, depRule *DependencyRule, cache 
map[*DelDepCacheKey]bool) (err error) {
+       id := &DelDepCacheKey{
+               key:  depRule.ServiceKey,
+               Type: path.DepsConsumer,
+       }
+       exist, ok := cache[id]
+       if !ok {
+               if depRule.ServiceKey.ServiceName == "*" {
+                       return nil
+               }
+
+               _, exist, err = FindServiceIds(ctx, depRule.ServiceKey.Version, 
depRule.ServiceKey)
+               if err != nil {
+                       return err
+               }
+
+               cache[id] = exist
+       }
+
+       filter := bson.M{
+               ColumnServiceKey: depRule.ServiceKey,
+       }
+       if !exist {
+               _, err = client.GetMongoClient().DocDelete(ctx, CollectionDep, 
filter)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func removeConsumerDeps(ctx context.Context, depRule *DependencyRule, cache 
map[*DelDepCacheKey]bool) (err error) {
+       var left []*discovery.MicroServiceKey
+       for _, key := range depRule.DepInfo.Dependency {
+               if key.ServiceName == "*" {
+                       left = append(left, key)
+                       continue
+               }
+
+               id := &DelDepCacheKey{
+                       key:  key,
+                       Type: path.DepsProvider,
+               }
+               exist, ok := cache[id]
+               if !ok {
+                       _, exist, err = FindServiceIds(ctx, key.Version, key)
+                       if err != nil {
+                               return err
+                       }
+                       cache[id] = exist
+               }
+
+               if exist {
+                       left = append(left, key)
+               }
+       }
+       if len(depRule.DepInfo.Dependency) == len(left) {
+               return nil
+       }
+
+       filter := bson.M{
+               ColumnServiceKey: depRule.ServiceKey,
+       }
+       if len(left) == 0 {
+               _, err = client.GetMongoClient().DocDelete(ctx, CollectionDep, 
filter)
+       } else {
+               updateData := bson.M{
+                       "$set": bson.M{StringBuilder([]string{ColumnDepInfo, 
ColumnDependency}): left},
+               }
+               _, err = client.GetMongoClient().Update(ctx, CollectionDep, 
filter, updateData)
+       }
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+func TransferToMicroServiceDependency(ctx context.Context, filter bson.M) 
(*discovery.MicroServiceDependency, error) {
+       microServiceDependency := &discovery.MicroServiceDependency{
+               Dependency: []*discovery.MicroServiceKey{},
+       }
+       findRes, err := client.GetMongoClient().FindOne(context.TODO(), 
CollectionDep, filter)
+       if err != nil {
+               return nil, err
+       }
+       if findRes.Err() == nil {
+               var depRule *DependencyRule
+               err := findRes.Decode(&depRule)
+               if err != nil {
+                       return nil, err
+               }
+               microServiceDependency.Dependency = 
append(microServiceDependency.Dependency, depRule.DepInfo.Dependency...)
+               return microServiceDependency, nil
+       }
+       return microServiceDependency, nil
+}
+
+func GetConsumerDepInfo(ctx context.Context, filter bson.M) 
([]*discovery.ConsumerDependency, error) {
+       var ConsumerDeps []*discovery.ConsumerDependency
+
+       findRes, err := client.GetMongoClient().Find(context.TODO(), 
CollectionDep, filter)
+       if err != nil {
+               return nil, err
+       }
+
+       for findRes.Next(ctx) {
+               var dep *ConsumerDep
+               err = findRes.Decode(&dep)
+               if err != nil {
+                       return nil, err
+               }
+               ConsumerDeps = append(ConsumerDeps, dep.ConsumerDepInfo)
+       }
+       return ConsumerDeps, nil
+}
+
+func GetServiceID(ctx context.Context, key *discovery.MicroServiceKey) 
(string, error) {
        id, err := getServiceID(ctx, GeneratorServiceNameFilter(ctx, key))
        if err != nil && !errors.Is(err, datasource.ErrNoData) {
                return "", err
diff --git a/datasource/mongo/dep_test.go b/datasource/mongo/dep_test.go
index 2b0f4fb..2e8bb33 100644
--- a/datasource/mongo/dep_test.go
+++ b/datasource/mongo/dep_test.go
@@ -33,7 +33,7 @@ func Test_Creat(t *testing.T) {
        )
 
        t.Run("create service, should be passed", func(t *testing.T) {
-               resp, err := 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err := 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                AppId:       "dep_create_dep_group",
                                ServiceName: "dep_create_dep_consumer",
@@ -47,7 +47,7 @@ func Test_Creat(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
                consumerId1 = resp.ServiceId
 
-               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
+               resp, err = 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                AppId:       "dep_create_dep_group",
                                ServiceName: "dep_create_dep_consumer_all",
@@ -61,7 +61,7 @@ func Test_Creat(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
                consumerId3 = resp.ServiceId
 
-               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
+               resp, err = 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                Environment: pb.ENV_PROD,
                                AppId:       "dep_create_dep_group",
@@ -76,7 +76,7 @@ func Test_Creat(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
                consumerId2 = resp.ServiceId
 
-               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
+               resp, err = 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                AppId:       "dep_create_dep_group",
                                ServiceName: "dep_create_dep_provider",
@@ -89,7 +89,7 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
+               resp, err = 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                AppId:       "dep_create_dep_group",
                                ServiceName: "dep_create_dep_provider",
@@ -102,7 +102,7 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
+               resp, err = 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                Environment: pb.ENV_PROD,
                                AppId:       "dep_create_dep_group",
@@ -132,7 +132,7 @@ func Test_Creat(t *testing.T) {
                }
 
                // consumer does not exist
-               resp, err := 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err := 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: &pb.MicroServiceKey{
                                        AppId:       "noexistapp",
@@ -147,7 +147,7 @@ func Test_Creat(t *testing.T) {
                assert.Equal(t, pb.ErrServiceNotExists, resp.GetCode())
 
                // provider in diff env
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
@@ -166,7 +166,7 @@ func Test_Creat(t *testing.T) {
 
                // consumer in diff env
                consumer.Environment = pb.ENV_PROD
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
@@ -182,17 +182,19 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respCon, err := 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respCon, err := 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
                assert.NotNil(t, respCon)
                assert.NoError(t, err)
+               assert.Equal(t, 0, len(respCon.Providers))
 
-               respCon, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respCon, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId2,
                })
                assert.NotNil(t, respCon)
                assert.NoError(t, err)
+               assert.Equal(t, 0, len(respCon.Providers))
        })
 
        t.Run("add dep and search, when request is valid, should be passed", 
func(t *testing.T) {
@@ -203,7 +205,7 @@ func Test_Creat(t *testing.T) {
                }
 
                // add latest
-               resp, err := 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err := 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
@@ -219,7 +221,7 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respPro, err := 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respPro, err := 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
                assert.NotNil(t, respPro)
@@ -228,7 +230,7 @@ func Test_Creat(t *testing.T) {
                assert.Equal(t, "1.0.1", respPro.Providers[0].Version)
 
                // add 1.0.0+
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
@@ -244,14 +246,15 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respPro, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
                assert.NotNil(t, respPro)
                assert.NoError(t, err)
+               assert.Equal(t, 2, len(respPro.Providers))
 
                // add *
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: &pb.MicroServiceKey{
                                        ServiceName: 
"dep_create_dep_consumer_all",
@@ -269,15 +272,15 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respPro, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId3,
                })
                assert.NotNil(t, respPro)
                assert.NoError(t, err)
-               assert.Equal(t, 0, len(respPro.Providers))
+               assert.NotEqual(t, 0, len(respPro.Providers))
 
                // clean all
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: &pb.MicroServiceKey{
                                        ServiceName: 
"dep_create_dep_consumer_all",
@@ -292,7 +295,7 @@ func Test_Creat(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
                // add multiple providers
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
@@ -312,7 +315,7 @@ func Test_Creat(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
                // add 1.0.0-2.0.0 to override *
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
@@ -328,15 +331,15 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respPro, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
                assert.NotNil(t, respPro)
                assert.NoError(t, err)
-               assert.Equal(t, "1.0.1", respPro.Providers[0].Version)
+               assert.Equal(t, "1.0.0", respPro.Providers[0].Version)
 
                // add not override
-               respAdd, err := 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               respAdd, err := 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
@@ -352,14 +355,14 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, respAdd.GetCode())
 
-               respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respPro, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
                assert.NotNil(t, respPro)
                assert.NoError(t, err)
 
                // add provider is empty
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer:  consumer,
                                Providers: []*pb.MicroServiceKey{},
@@ -369,7 +372,7 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(depGetContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: consumer,
                        },
@@ -378,7 +381,7 @@ func Test_Creat(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respPro, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
                assert.NotNil(t, respPro)
@@ -394,7 +397,7 @@ func Test_Get(t *testing.T) {
        )
 
        t.Run("create service, should be passed", func(t *testing.T) {
-               resp, err := 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err := 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                AppId:       "dep_get_dep_group",
                                ServiceName: "dep_get_dep_consumer",
@@ -408,7 +411,7 @@ func Test_Get(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
                consumerId1 = resp.ServiceId
 
-               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
+               resp, err = 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                AppId:       "dep_get_dep_group",
                                ServiceName: "dep_get_dep_provider",
@@ -422,7 +425,7 @@ func Test_Get(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
                providerId1 = resp.ServiceId
 
-               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
+               resp, err = 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                AppId:       "dep_get_dep_group",
                                ServiceName: "dep_get_dep_provider",
@@ -439,14 +442,14 @@ func Test_Get(t *testing.T) {
 
        t.Run("search dep, when request is valid, should be passed", func(t 
*testing.T) {
                //get provider
-               resp, err := 
datasource.Instance().SearchProviderDependency(getContext(), 
&pb.GetDependenciesRequest{
+               resp, err := 
datasource.Instance().SearchProviderDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: providerId1,
                })
                assert.NotNil(t, resp)
                assert.NoError(t, err)
 
                //get consumer
-               resp, err = 
datasource.Instance().SearchProviderDependency(getContext(), 
&pb.GetDependenciesRequest{
+               resp, err = 
datasource.Instance().SearchProviderDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
                assert.NotNil(t, resp)
@@ -455,7 +458,7 @@ func Test_Get(t *testing.T) {
 
        t.Run("when after finding instance, should created dependencies between 
C and P", func(t *testing.T) {
                // find provider
-               resp, err := datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+               resp, err := 
datasource.Instance().FindInstances(depGetContext(), &pb.FindInstancesRequest{
                        ConsumerServiceId: consumerId1,
                        AppId:             "dep_get_dep_group",
                        ServiceName:       "dep_get_dep_provider",
@@ -466,21 +469,21 @@ func Test_Get(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
                // get consumer's deps
-               respGetP, err := 
datasource.Instance().SearchProviderDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respGetP, err := 
datasource.Instance().SearchProviderDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: providerId1,
                })
                assert.NotNil(t, respGetP)
                assert.NoError(t, err)
 
                // get provider's deps
-               respGetC, err := 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respGetC, err := 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
                assert.NotNil(t, respGetC)
                assert.NoError(t, err)
 
                // get self deps
-               resp, err = datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+               resp, err = 
datasource.Instance().FindInstances(depGetContext(), &pb.FindInstancesRequest{
                        ConsumerServiceId: consumerId1,
                        AppId:             "dep_get_dep_group",
                        ServiceName:       "dep_get_dep_consumer",
@@ -490,7 +493,7 @@ func Test_Get(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-               respGetC, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respGetC, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                        NoSelf:    true,
                })
@@ -498,7 +501,7 @@ func Test_Get(t *testing.T) {
                assert.NoError(t, err)
 
                // find before provider register
-               resp, err = datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+               resp, err = 
datasource.Instance().FindInstances(depGetContext(), &pb.FindInstancesRequest{
                        ConsumerServiceId: providerId2,
                        AppId:             "dep_get_dep_group",
                        ServiceName:       "dep_get_dep_finder",
@@ -508,7 +511,7 @@ func Test_Get(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
 
-               respCreateF, err := 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               respCreateF, err := 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                AppId:       "dep_get_dep_group",
                                ServiceName: "dep_get_dep_finder",
@@ -522,7 +525,7 @@ func Test_Get(t *testing.T) {
                assert.Equal(t, pb.ResponseSuccess, 
respCreateF.Response.GetCode())
                finder1 := respCreateF.ServiceId
 
-               resp, err = datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+               resp, err = 
datasource.Instance().FindInstances(depGetContext(), &pb.FindInstancesRequest{
                        ConsumerServiceId: providerId2,
                        AppId:             "dep_get_dep_group",
                        ServiceName:       "dep_get_dep_finder",
@@ -532,28 +535,30 @@ func Test_Get(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-               respGetC, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respGetC, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: providerId2,
                })
                assert.NotNil(t, respGetC)
                assert.NoError(t, err)
+               assert.Equal(t, 1, len(respGetC.Providers))
+               assert.Equal(t, finder1, respGetC.Providers[0].ServiceId)
 
                // find after delete micro service
-               respDelP, err := 
datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
+               respDelP, err := 
datasource.Instance().UnregisterService(depGetContext(), 
&pb.DeleteServiceRequest{
                        ServiceId: finder1, Force: true,
                })
                assert.NotNil(t, respDelP)
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, respDelP.Response.GetCode())
 
-               respGetC, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respGetC, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: providerId2,
                })
                assert.NotNil(t, respGetC)
                assert.NoError(t, err)
                assert.Equal(t, 0, len(respGetC.Providers))
 
-               respCreateF, err = 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               respCreateF, err = 
datasource.Instance().RegisterService(depGetContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
                                ServiceId:   finder1,
                                AppId:       "dep_get_dep_group",
@@ -567,7 +572,7 @@ func Test_Get(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, 
respCreateF.Response.GetCode())
 
-               resp, err = datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+               resp, err = 
datasource.Instance().FindInstances(depGetContext(), &pb.FindInstancesRequest{
                        ConsumerServiceId: providerId2,
                        AppId:             "dep_get_dep_group",
                        ServiceName:       "dep_get_dep_finder",
@@ -577,11 +582,12 @@ func Test_Get(t *testing.T) {
                assert.NoError(t, err)
                assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-               respGetC, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respGetC, err = 
datasource.Instance().SearchConsumerDependency(depGetContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: providerId2,
                })
                assert.NotNil(t, respGetC)
                assert.NoError(t, err)
-               assert.Equal(t, 0, len(respGetC.Providers))
+               assert.Equal(t, 1, len(respGetC.Providers))
+               assert.Equal(t, finder1, respGetC.Providers[0].ServiceId)
        })
 }
diff --git a/datasource/mongo/dependency_query.go 
b/datasource/mongo/dependency_query.go
index d404f90..c245dbe 100644
--- a/datasource/mongo/dependency_query.go
+++ b/datasource/mongo/dependency_query.go
@@ -23,6 +23,9 @@ import (
        "fmt"
        "strings"
 
+       "github.com/apache/servicecomb-service-center/datasource/etcd/path"
+       "github.com/apache/servicecomb-service-center/pkg/validate"
+
        "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/datasource/mongo/client"
        "github.com/apache/servicecomb-service-center/pkg/log"
@@ -147,9 +150,80 @@ func (dr *DependencyRelation) 
GetDependencyConsumersOfProvider() ([]*pb.MicroSer
                log.Error(fmt.Sprintf("get consumers that depend on all 
services failed, %s", dr.provider.ServiceId), err)
                return nil, err
        }
+       providerService := pb.MicroServiceToKey(dr.domainProject, dr.provider)
+       consumerDependList, err := 
dr.GetConsumerOfSameServiceNameAndAppID(providerService)
+       if err != nil {
+               log.Errorf(err, "get consumers that depend on rule[%s/%s/%s/%s] 
failed",
+                       dr.provider.Environment, dr.provider.AppId, 
dr.provider.ServiceName, dr.provider.Version)
+               return nil, err
+       }
+       consumerDependAllList = append(consumerDependAllList, 
consumerDependList...)
        return consumerDependAllList, nil
 }
 
+func (dr *DependencyRelation) GetConsumerOfSameServiceNameAndAppID(provider 
*pb.MicroServiceKey) ([]*pb.MicroServiceKey, error) {
+       providerVersion := provider.Version
+       provider.Version = ""
+       filter := GenerateRuleKeyWithSameServiceNameAndAppID(path.DepsProvider, 
dr.domainProject, provider)
+       provider.Version = providerVersion
+       depRules, err := getServiceKeysInDep(dr.ctx, filter)
+       if err != nil {
+               return nil, err
+       }
+       var allConsumers []*pb.MicroServiceKey
+       var latestServiceID []string
+
+       for _, depRule := range depRules {
+               providerVersionRule := depRule.ServiceKey.Version
+               if providerVersionRule == "latest" {
+                       if latestServiceID == nil {
+                               latestServiceID, _, err = 
FindServiceIds(dr.ctx, providerVersionRule, provider)
+                               if err != nil {
+                                       log.Error(fmt.Sprintf("get 
service[%s/%s/%s/%s]'s serviceID failed",
+                                               provider.Environment, 
provider.AppId, provider.ServiceName, providerVersionRule), err)
+                                       return nil, err
+                               }
+                       }
+                       if len(latestServiceID) == 0 {
+                               log.Info(fmt.Sprintf("service[%s/%s/%s/%s] does 
not exist",
+                                       provider.Environment, provider.AppId, 
provider.ServiceName, providerVersionRule))
+                               continue
+                       }
+                       if dr.provider.ServiceId != latestServiceID[0] {
+                               continue
+                       }
+               } else {
+                       if !VersionMatchRule(providerVersion, 
providerVersionRule) {
+                               continue
+                       }
+               }
+               if len(depRule.DepInfo.Dependency) > 0 {
+                       allConsumers = append(allConsumers, 
depRule.DepInfo.Dependency...)
+               }
+       }
+       return allConsumers, nil
+}
+
+// not prepare for latest scene, should merge it with find serviceids func.
+func VersionMatchRule(version, versionRule string) bool {
+       if len(versionRule) == 0 {
+               return false
+       }
+       rangeIdx := strings.Index(versionRule, "-")
+       versionInt, _ := validate.VersionToInt64(version)
+       switch {
+       case versionRule[len(versionRule)-1:] == "+":
+               start, _ := 
validate.VersionToInt64(versionRule[:len(versionRule)-1])
+               return versionInt >= start
+       case rangeIdx > 0:
+               start, _ := validate.VersionToInt64(versionRule[:rangeIdx])
+               end, _ := validate.VersionToInt64(versionRule[rangeIdx+1:])
+               return versionInt >= start && versionInt < end
+       default:
+               return version == versionRule
+       }
+}
+
 func (dr *DependencyRelation) GetServiceByMicroServiceKey(service 
*pb.MicroServiceKey) (*pb.MicroService, error) {
        filter, err := MicroServiceKeyFilter(service)
        if err != nil {
@@ -180,7 +254,7 @@ func (dr *DependencyRelation) 
GetServiceByMicroServiceKey(service *pb.MicroServi
 func (dr *DependencyRelation) getConsumerOfDependAllServices() 
([]*pb.MicroServiceKey, error) {
        providerService := pb.MicroServiceToKey(dr.domainProject, dr.provider)
        providerService.ServiceName = "*"
-       filter := GenerateProviderDependencyRuleKey(dr.domainProject, 
dr.provider.ServiceId, providerService)
+       filter := GenerateProviderDependencyRuleKey(dr.domainProject, 
providerService)
        findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionDep, 
filter)
        if err != nil {
                return nil, err
@@ -191,43 +265,46 @@ func (dr *DependencyRelation) 
getConsumerOfDependAllServices() ([]*pb.MicroServi
 
        var msKeys []*pb.MicroServiceKey
        for findRes.Next(dr.ctx) {
-               var dep *Dependency
-               err = findRes.Decode(&dep)
+               var depRule *DependencyRule
+               err = findRes.Decode(&depRule)
                if err != nil {
                        return nil, err
                }
-               msKeys = append(msKeys, dep.DependencyInfo.Consumer)
+               msKeys = append(msKeys, depRule.ServiceKey)
        }
        return msKeys, nil
 }
 
-func (dr *DependencyRelation) getProviderKeys() ([]*pb.MicroServiceKey, error) 
{
-       if dr.consumer == nil {
-               return nil, ErrInvalidConsumer
-       }
-       consumerMicroServiceKey := pb.MicroServiceToKey(dr.domainProject, 
dr.consumer)
-       filter := GenerateConsumerDependencyRuleKey(dr.domainProject, 
dr.consumer.ServiceId, consumerMicroServiceKey)
-       findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionDep, 
filter)
+func getServiceKeysInDep(ctx context.Context, filter interface{}) 
([]*DependencyRule, error) {
+       findRes, err := client.GetMongoClient().Find(ctx, CollectionDep, filter)
        if err != nil {
                return nil, err
        }
-       if findRes.Err() != nil {
-               return nil, findRes.Err()
-       }
-       var dep *Dependency
-       for findRes.Next(dr.ctx) {
-               err = findRes.Decode(&dep)
+       defer findRes.Close(ctx)
+       var depRules []*DependencyRule
+       for findRes.Next(ctx) {
+               var tmp *DependencyRule
+               err := findRes.Decode(&tmp)
                if err != nil {
                        return nil, err
                }
-               if dep != nil {
-                       break
-               }
+               depRules = append(depRules, tmp)
        }
-       if dep != nil {
-               return dep.DependencyInfo.Providers, nil
+       return depRules, nil
+}
+
+func (dr *DependencyRelation) getProviderKeys() ([]*pb.MicroServiceKey, error) 
{
+       if dr.consumer == nil {
+               return nil, ErrInvalidConsumer
        }
-       return nil, nil
+       consumerMicroServiceKey := pb.MicroServiceToKey(dr.domainProject, 
dr.consumer)
+       filter := GenerateConsumerDependencyRuleKey(dr.domainProject, 
consumerMicroServiceKey)
+
+       consumerDependency, err := TransferToMicroServiceDependency(dr.ctx, 
filter)
+       if err != nil {
+               return nil, err
+       }
+       return consumerDependency.Dependency, nil
 }
 
 func (dr *DependencyRelation) parseDependencyRule(dependencyRule 
*pb.MicroServiceKey) (serviceIDs []string, err error) {
@@ -235,7 +312,7 @@ func (dr *DependencyRelation) 
parseDependencyRule(dependencyRule *pb.MicroServic
        case dependencyRule.ServiceName == "*":
                log.Info(fmt.Sprintf("service[%s/%s/%s/%s] rely all service",
                        dr.consumer.Environment, dr.consumer.AppId, 
dr.consumer.ServiceName, dr.consumer.Version))
-               filter, err := MicroServiceKeyFilter(dependencyRule)
+               filter, err := RelyAllServiceKey(dependencyRule)
                if err != nil {
                        log.Error("get serivce failed", err)
                        return nil, err
@@ -244,9 +321,6 @@ func (dr *DependencyRelation) 
parseDependencyRule(dependencyRule *pb.MicroServic
                if err != nil {
                        return nil, err
                }
-               if findRes.Err() != nil {
-                       return nil, findRes.Err()
-               }
                for findRes.Next(dr.ctx) {
                        var service Service
                        err = findRes.Decode(&service)
@@ -298,42 +372,152 @@ func MicroServiceKeyFilter(key *pb.MicroServiceKey) 
(bson.M, error) {
                StringBuilder([]string{ColumnServiceInfo, ColumnVersion}): 
key.Version}, nil
 }
 
-func FindServiceIds(ctx context.Context, versionRule string, key 
*pb.MicroServiceKey) (serviceIDs []string, b bool, err error) {
-       match, err := ParseVersionRule(ctx, versionRule, key)
-       if err != nil {
+func RelyAllServiceKey(key *pb.MicroServiceKey) (bson.M, error) {
+       tenant := strings.Split(key.Tenant, "/")
+       if len(tenant) != 2 {
+               return nil, ErrInvalidDomainProject
+       }
+       return bson.M{
+               ColumnDomain:  tenant[0],
+               ColumnProject: tenant[1],
+               StringBuilder([]string{ColumnServiceInfo, ColumnEnv}): 
key.Environment}, nil
+}
+
+func FindServiceIds(ctx context.Context, versionRule string, key 
*pb.MicroServiceKey) ([]string, bool, error) {
+       if len(versionRule) == 0 {
+               return nil, false, nil
+       }
+
+       tenant := strings.Split(key.Tenant, "/")
+       if len(tenant) != 2 {
                return nil, false, ErrInvalidDomainProject
        }
-       if match == nil {
-               tenant := strings.Split(key.Tenant, "/")
-               if len(tenant) != 2 {
-                       return nil, false, ErrInvalidDomainProject
+
+       baseFilter := bson.D{
+               {Key: ColumnDomain, Value: tenant[0]},
+               {Key: ColumnProject, Value: tenant[1]},
+               {Key: StringBuilder([]string{ColumnServiceInfo, ColumnEnv}), 
Value: key.Environment},
+               {Key: StringBuilder([]string{ColumnServiceInfo, ColumnAppID}), 
Value: key.AppId}}
+
+       serviceIds, exist, err := findServiceKeysByServiceName(ctx, 
versionRule, key, baseFilter)
+       if err != nil {
+               return nil, false, err
+       }
+       if len(serviceIds) == 0 {
+               if exist {
+                       // service exist but version not matched
+                       return nil, true, nil
                }
-               filter := bson.M{
-                       ColumnDomain:  tenant[0],
-                       ColumnProject: tenant[1],
-                       StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):  
       key.Environment,
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnVersion}):     versionRule,
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnAppID}):       key.AppId,
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnServiceName}): key.ServiceName,
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnAlias}):       key.Alias}
-               findRes, err := client.GetMongoClient().Find(ctx, 
CollectionService, filter)
-               if err != nil {
+               if len(key.Alias) == 0 {
                        return nil, false, nil
                }
-               if findRes.Err() != nil {
-                       return nil, false, findRes.Err()
+               serviceIds, exist, err = findServiceKeysByAlias(ctx, 
versionRule, key, baseFilter)
+               if err != nil {
+                       return nil, false, err
                }
-               for findRes.Next(ctx) {
-                       var service Service
-                       err = findRes.Decode(&service)
-                       if err != nil {
-                               return nil, false, err
-                       }
-                       serviceIDs = append(serviceIDs, 
service.ServiceInfo.ServiceId)
+               return serviceIds, exist, nil
+       }
+       return serviceIds, exist, nil
+}
+
+func serviceVersionFilter(ctx context.Context, versionRule string, filter 
bson.D) ([]string, bool, error) {
+       baseExist, err := client.GetMongoClient().DocExist(ctx, 
CollectionService, filter)
+       if err != nil || !baseExist {
+               return nil, false, err
+       }
+       filterFunc, newFilter := findServiceKeys(ctx, versionRule, filter)
+       if filterFunc == nil {
+               //精确匹配,无version返回服务不存在而不是verison匹配错误
+               ids, err := GetVersionService(ctx, newFilter)
+               if err != nil || len(ids) == 0 {
+                       return nil, false, err
                }
-               return serviceIDs, false, nil
+               return ids, true, nil
+       }
+
+       ids, err := filterFunc(ctx, newFilter)
+       if err != nil {
+               return nil, false, err
        }
-       return match, false, nil
+       return ids, true, nil
+}
+
+func findServiceKeysByServiceName(ctx context.Context, versionRule string, key 
*pb.MicroServiceKey, baseFilter bson.D) ([]string, bool, error) {
+       filter := append(baseFilter,
+               bson.E{Key: StringBuilder([]string{ColumnServiceInfo, 
ColumnServiceName}), Value: key.ServiceName})
+       return serviceVersionFilter(ctx, versionRule, filter)
+}
+
+func findServiceKeysByAlias(ctx context.Context, versionRule string, key 
*pb.MicroServiceKey, baseFilter bson.D) ([]string, bool, error) {
+       filter := append(baseFilter,
+               bson.E{Key: StringBuilder([]string{ColumnServiceInfo, 
ColumnAlias}), Value: key.Alias})
+       return serviceVersionFilter(ctx, versionRule, filter)
+}
+
+type ServiceVersionFilter func(ctx context.Context, filter bson.D) ([]string, 
error)
+
+func findServiceKeys(ctx context.Context, versionRule string, filter bson.D) 
(filterFunc ServiceVersionFilter, newFilter bson.D) {
+       rangeIdx := strings.Index(versionRule, "-")
+       switch {
+       case versionRule == "latest":
+               return GetVersionServiceLatest, filter
+       case versionRule[len(versionRule)-1:] == "+":
+               start := versionRule[:len(versionRule)-1]
+               filter = append(filter, bson.E{Key: 
StringBuilder([]string{ColumnServiceInfo, ColumnVersion}), Value: 
bson.M{"$gte": start}})
+               return GetVersionService, filter
+       case rangeIdx > 0:
+               start := versionRule[:rangeIdx]
+               end := versionRule[rangeIdx+1:]
+               filter = append(filter, bson.E{Key: 
StringBuilder([]string{ColumnServiceInfo, ColumnVersion}), Value: 
bson.M{"$gte": start, "$lt": end}})
+               return GetVersionService, filter
+       default:
+               filter = append(filter, bson.E{Key: 
StringBuilder([]string{ColumnServiceInfo, ColumnVersion}), Value: versionRule})
+               return nil, filter
+       }
+}
+
+func GetVersionServiceLatest(ctx context.Context, m bson.D) (serviceIds 
[]string, err error) {
+       findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m,
+               &options.FindOptions{
+                       Sort: bson.M{StringBuilder([]string{ColumnServiceInfo, 
ColumnVersion}): -1}})
+       if err != nil {
+               return nil, err
+       }
+       if findRes.Err() != nil {
+               return nil, findRes.Err()
+       }
+       for findRes.Next(ctx) {
+               var service *Service
+               err = findRes.Decode(&service)
+               if err != nil {
+                       return
+               }
+               serviceIds = append(serviceIds, service.ServiceInfo.ServiceId)
+               if serviceIds != nil {
+                       return
+               }
+       }
+       return
+}
+
+func GetVersionService(ctx context.Context, m bson.D) (serviceIds []string, 
err error) {
+       findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m, 
&options.FindOptions{
+               Sort: bson.M{StringBuilder([]string{ColumnServiceInfo, 
ColumnVersion}): -1}})
+       if err != nil {
+               return
+       }
+       if findRes.Err() != nil {
+               return nil, findRes.Err()
+       }
+       for findRes.Next(ctx) {
+               var service *Service
+               err = findRes.Decode(&service)
+               if err != nil {
+                       return
+               }
+               serviceIds = append(serviceIds, service.ServiceInfo.ServiceId)
+       }
+       return
 }
 
 func ParseVersionRule(ctx context.Context, versionRule string, key 
*pb.MicroServiceKey) ([]string, error) {
@@ -445,32 +629,40 @@ func ToDependencyRelationFilterOpt(opts 
...DependencyRelationFilterOption) (op D
        return
 }
 
-func GenerateConsumerDependencyRuleKey(domainProject string, serviceID string, 
in *pb.MicroServiceKey) bson.M {
-       return GenerateServiceDependencyRuleKey(domainProject, serviceID, in)
+func GenerateConsumerDependencyRuleKey(domainProject string, in 
*pb.MicroServiceKey) bson.M {
+       return GenerateServiceDependencyRuleKey(path.DepsConsumer, 
domainProject, in)
+}
+
+func GenerateProviderDependencyRuleKey(domainProject string, in 
*pb.MicroServiceKey) bson.M {
+       return GenerateServiceDependencyRuleKey(path.DepsProvider, 
domainProject, in)
 }
 
-func GenerateProviderDependencyRuleKey(domainProject string, serviceID string, 
in *pb.MicroServiceKey) bson.M {
-       return GenerateServiceDependencyRuleKey(domainProject, serviceID, in)
+func GenerateRuleKeyWithSameServiceNameAndAppID(serviceType string, 
domainProject string, in *pb.MicroServiceKey) bson.M {
+       return bson.M{
+               ColumnServiceType: serviceType,
+               StringBuilder([]string{ColumnServiceKey, ColumnTenant}):      
domainProject,
+               StringBuilder([]string{ColumnServiceKey, ColumnAppID}):       
in.AppId,
+               StringBuilder([]string{ColumnServiceKey, ColumnServiceName}): 
in.ServiceName}
 }
 
-func GenerateServiceDependencyRuleKey(domainProject string, serviceID string, 
in *pb.MicroServiceKey) bson.M {
+func GenerateServiceDependencyRuleKey(serviceType string, domainProject 
string, in *pb.MicroServiceKey) bson.M {
        if in == nil {
                return bson.M{
-                       ColumnConsumerID: serviceID,
-                       StringBuilder([]string{ColumnDependencyInfo, 
ColumnConsumer, ColumnTenant}): domainProject}
+                       ColumnServiceType: serviceType,
+                       StringBuilder([]string{ColumnServiceKey, 
ColumnTenant}): domainProject}
        }
        if in.ServiceName == "*" {
                return bson.M{
-                       ColumnConsumerID: serviceID,
-                       StringBuilder([]string{ColumnDependencyInfo, 
ColumnConsumer, ColumnTenant}):      domainProject,
-                       StringBuilder([]string{ColumnDependencyInfo, 
ColumnConsumer, ColumnEnv}):         in.Environment,
-                       StringBuilder([]string{ColumnDependencyInfo, 
ColumnConsumer, ColumnServiceName}): in.ServiceName}
+                       ColumnServiceType: serviceType,
+                       StringBuilder([]string{ColumnServiceKey, 
ColumnTenant}):      domainProject,
+                       StringBuilder([]string{ColumnServiceKey, ColumnEnv}):   
      in.Environment,
+                       StringBuilder([]string{ColumnServiceKey, 
ColumnServiceName}): in.ServiceName}
        }
        return bson.M{
-               ColumnConsumerID: serviceID,
-               StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, 
ColumnTenant}):      domainProject,
-               StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, 
ColumnEnv}):         in.Environment,
-               StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, 
ColumnAppID}):       in.AppId,
-               StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, 
ColumnVersion}):     in.Version,
-               StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, 
ColumnServiceName}): in.ServiceName}
+               ColumnServiceType: serviceType,
+               StringBuilder([]string{ColumnServiceKey, ColumnTenant}):      
domainProject,
+               StringBuilder([]string{ColumnServiceKey, ColumnEnv}):         
in.Environment,
+               StringBuilder([]string{ColumnServiceKey, ColumnAppID}):       
in.AppId,
+               StringBuilder([]string{ColumnServiceKey, ColumnVersion}):     
in.Version,
+               StringBuilder([]string{ColumnServiceKey, ColumnServiceName}): 
in.ServiceName}
 }
diff --git a/datasource/mongo/mongo_suite_test.go 
b/datasource/mongo/mongo_suite_test.go
index c35c5c1..f08972a 100644
--- a/datasource/mongo/mongo_suite_test.go
+++ b/datasource/mongo/mongo_suite_test.go
@@ -46,6 +46,10 @@ func getContext() context.Context {
        return util.WithNoCache(util.SetDomainProject(context.Background(), 
"default", "default"))
 }
 
+func depGetContext() context.Context {
+       return util.WithNoCache(util.SetDomainProject(context.Background(), 
"new_default", "new_default"))
+}
+
 func TestMongo(t *testing.T) {
        RegisterFailHandler(Fail)
        junitReporter := reporters.NewJUnitReporter("mongo.junit.xml")
diff --git a/datasource/mongo/ms.go b/datasource/mongo/ms.go
index 7152e78..0a769ee 100644
--- a/datasource/mongo/ms.go
+++ b/datasource/mongo/ms.go
@@ -232,40 +232,39 @@ func (ds *DataSource) ExistServiceByID(ctx 
context.Context, request *discovery.G
 }
 
 func (ds *DataSource) ExistService(ctx context.Context, request 
*discovery.GetExistenceRequest) (*discovery.GetExistenceResponse, error) {
-       serviceKey := &discovery.MicroServiceKey{
+       domainProject := util.ParseDomainProject(ctx)
+       serviceFlag := util.StringJoin([]string{
+               request.Environment, request.AppId, request.ServiceName, 
request.Version}, "/")
+
+       ids, exist, err := FindServiceIds(ctx, request.Version, 
&discovery.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))
+               Tenant:      domainProject,
+       })
        if err != nil {
+               log.Error(fmt.Sprintf("micro-service[%s] exist failed, find 
serviceIDs failed", serviceFlag), err)
                return &discovery.GetExistenceResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
        }
-       if len(services) != 0 {
+       if !exist {
+               log.Info(fmt.Sprintf("micro-service[%s] exist failed, service 
does not exist", serviceFlag))
                return &discovery.GetExistenceResponse{
-                       Response:  
discovery.CreateResponse(discovery.ResponseSuccess, "get service id 
successfully."),
-                       ServiceId: services[0].ServiceId,
+                       Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, serviceFlag+" does not 
exist."),
                }, nil
        }
-       services, err = GetServices(ctx, GeneratorServiceAliasFilter(ctx, 
serviceKey))
-       if err != nil {
-               return &discovery.GetExistenceResponse{
-                       Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
-               }, err
-       }
-       if len(services) != 0 {
+       if len(ids) == 0 {
+               log.Info(fmt.Sprintf("micro-service[%s] exist failed, version 
mismatch", serviceFlag))
                return &discovery.GetExistenceResponse{
-                       Response:  
discovery.CreateResponse(discovery.ResponseSuccess, "get service id 
successfully."),
-                       ServiceId: services[0].ServiceId,
+                       Response: 
discovery.CreateResponse(discovery.ErrServiceVersionNotExists, serviceFlag+" 
version mismatch."),
                }, nil
        }
        return &discovery.GetExistenceResponse{
-               Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, "Service does not 
exist"),
+               Response:  discovery.CreateResponse(discovery.ResponseSuccess, 
"get service id successfully."),
+               ServiceId: ids[0], // 约定多个时,取较新版本
        }, nil
 }
 
@@ -292,7 +291,7 @@ func (ds *DataSource) DelServicePri(ctx context.Context, 
serviceID string, force
                log.Error(fmt.Sprintf("%s micro-service %s failed, operator: 
%s", title, serviceID, remoteIP), ErrNotAllowDeleteSC)
                return discovery.CreateResponse(discovery.ErrInvalidParams, 
ErrNotAllowDeleteSC.Error()), nil
        }
-       _, err := GetService(ctx, GeneratorServiceFilter(ctx, serviceID))
+       microservice, err := GetService(ctx, GeneratorServiceFilter(ctx, 
serviceID))
        if err != nil {
                if errors.Is(err, datasource.ErrNoData) {
                        log.Debug(fmt.Sprintf("%s micro-service %s failed, 
service does not exist, operator: %s",
@@ -305,6 +304,18 @@ func (ds *DataSource) DelServicePri(ctx context.Context, 
serviceID string, force
        }
        // 强制删除,则与该服务相关的信息删除,非强制删除: 
如果作为该被依赖(作为provider,提供服务,且不是只存在自依赖)或者存在实例,则不能删除
        if !force {
+               dr := NewProviderDependencyRelation(ctx, 
util.ParseDomainProject(ctx), microservice.ServiceInfo)
+               services, err := dr.GetDependencyConsumerIds()
+               if err != nil {
+                       log.Error(fmt.Sprintf("delete micro-service[%s] failed, 
get service dependency failed, operator: %s",
+                               serviceID, remoteIP), err)
+                       return discovery.CreateResponse(discovery.ErrInternal, 
err.Error()), err
+               }
+               if l := len(services); l > 1 || (l == 1 && services[0] != 
serviceID) {
+                       log.Error(fmt.Sprintf("delete micro-service[%s] failed, 
other services[%d] depend on it, operator: %s",
+                               serviceID, l, remoteIP), err)
+                       return 
discovery.CreateResponse(discovery.ErrDependedOnConsumer, "Can not delete this 
service, other service rely it."), err
+               }
                //todo wait for dep interface
                instancesExist, err := client.GetMongoClient().DocExist(ctx, 
CollectionInstance, bson.M{StringBuilder([]string{ColumnInstanceInfo, 
ColumnServiceID}): serviceID})
                if err != nil {
@@ -319,7 +330,7 @@ func (ds *DataSource) DelServicePri(ctx context.Context, 
serviceID string, force
                }
 
        }
-       //todo del dep
+
        schemaOps := client.MongoOperation{Table: CollectionSchema, Models: 
[]mongo.WriteModel{mongo.NewDeleteManyModel().SetFilter(bson.M{ColumnServiceID: 
serviceID})}}
        rulesOps := client.MongoOperation{Table: CollectionRule, Models: 
[]mongo.WriteModel{mongo.NewDeleteManyModel().SetFilter(bson.M{ColumnServiceID: 
serviceID})}}
        instanceOps := client.MongoOperation{Table: CollectionInstance, Models: 
[]mongo.WriteModel{mongo.NewDeleteManyModel().SetFilter(bson.M{StringBuilder([]string{ColumnInstanceInfo,
 ColumnServiceID}): serviceID})}}
@@ -330,6 +341,23 @@ func (ds *DataSource) DelServicePri(ctx context.Context, 
serviceID string, force
                log.Error(fmt.Sprintf("micro-service[%s] failed, operator: %s", 
serviceID, remoteIP), err)
                return 
discovery.CreateResponse(discovery.ErrUnavailableBackend, err.Error()), err
        }
+
+       domainProject := util.ToDomainProject(microservice.Domain, 
microservice.Project)
+       serviceKey := &discovery.MicroServiceKey{
+               Tenant:      domainProject,
+               Environment: microservice.ServiceInfo.Environment,
+               AppId:       microservice.ServiceInfo.AppId,
+               ServiceName: microservice.ServiceInfo.ServiceName,
+               Version:     microservice.ServiceInfo.Version,
+               Alias:       microservice.ServiceInfo.Alias,
+       }
+
+       err = DeleteDependencyForDeleteService(domainProject, serviceID, 
serviceKey)
+       if err != nil {
+               log.Error(fmt.Sprintf("micro-service[%s] failed, operator: %s", 
serviceID, remoteIP), err)
+               return 
discovery.CreateResponse(discovery.ErrUnavailableBackend, err.Error()), err
+       }
+
        return discovery.CreateResponse(discovery.ResponseSuccess, "Unregister 
service successfully."), nil
 }
 
@@ -1254,6 +1282,7 @@ func GetServicesVersions(ctx context.Context, filter 
interface{}) ([]string, err
 func getServiceDetailUtil(ctx context.Context, mgs *Service, countOnly bool, 
options []string) (*discovery.ServiceDetail, error) {
        serviceDetail := new(discovery.ServiceDetail)
        serviceID := mgs.ServiceInfo.ServiceId
+       domainProject := util.ParseDomainProject(ctx)
        if countOnly {
                serviceDetail.Statics = new(discovery.Statistics)
        }
@@ -1298,7 +1327,21 @@ func getServiceDetailUtil(ctx context.Context, mgs 
*Service, countOnly bool, opt
                        }
                        serviceDetail.SchemaInfos = schemas
                case "dependencies":
-                       //todo wait dependency interface
+                       service := mgs.ServiceInfo
+                       dr := NewDependencyRelation(ctx, domainProject, 
service, service)
+                       consumers, err := 
dr.GetDependencyConsumers(WithoutSelfDependency(), WithSameDomainProject())
+                       if err != nil {
+                               log.Error(fmt.Sprintf("get 
service[%s][%s/%s/%s/%s]'s all consumers failed",
+                                       service.ServiceId, service.Environment, 
service.AppId, service.ServiceName, service.Version), err)
+                       }
+                       providers, err := 
dr.GetDependencyProviders(WithoutSelfDependency(), WithSameDomainProject())
+                       if err != nil {
+                               log.Error(fmt.Sprintf("get 
service[%s][%s/%s/%s/%s]'s all providers failed",
+                                       service.ServiceId, service.Environment, 
service.AppId, service.ServiceName, service.Version), err)
+                               return nil, err
+                       }
+                       serviceDetail.Consumers = consumers
+                       serviceDetail.Providers = providers
                case "":
                        continue
                default:
@@ -2208,9 +2251,58 @@ func (ds *DataSource) reshapeProviderKey(ctx 
context.Context, provider *discover
 }
 
 func AddServiceVersionRule(ctx context.Context, domainProject string, consumer 
*discovery.MicroService, provider *discovery.MicroServiceKey) error {
+       consumerKey := discovery.MicroServiceToKey(domainProject, consumer)
+       exist, err := DependencyRuleExist(ctx, provider, consumerKey)
+       if exist || err != nil {
+               return err
+       }
+
+       r := &discovery.ConsumerDependency{
+               Consumer:  consumerKey,
+               Providers: []*discovery.MicroServiceKey{provider},
+               Override:  false,
+       }
+       err = syncDependencyRule(ctx, domainProject, r)
+
+       if err != nil {
+               return err
+       }
+
        return nil
 }
 
+func DependencyRuleExist(ctx context.Context, provider 
*discovery.MicroServiceKey, consumer *discovery.MicroServiceKey) (bool, error) {
+       targetDomainProject := provider.Tenant
+       if len(targetDomainProject) == 0 {
+               targetDomainProject = consumer.Tenant
+       }
+       consumerKey := GenerateConsumerDependencyRuleKey(consumer.Tenant, 
consumer)
+       existed, err := DependencyRuleExistUtil(ctx, consumerKey, provider)
+       if err != nil || existed {
+               return existed, err
+       }
+       providerKey := GenerateProviderDependencyRuleKey(targetDomainProject, 
provider)
+       return DependencyRuleExistUtil(ctx, providerKey, consumer)
+}
+
+func DependencyRuleExistUtil(ctx context.Context, key bson.M, target 
*discovery.MicroServiceKey) (bool, error) {
+       compareData, err := TransferToMicroServiceDependency(ctx, key)
+       if err != nil {
+               return false, err
+       }
+
+       if len(compareData.Dependency) != 0 {
+               isEqual, err := 
datasource.ContainServiceDependency(compareData.Dependency, target)
+               if err != nil {
+                       return false, err
+               }
+               if isEqual {
+                       return true, nil
+               }
+       }
+       return false, nil
+}
+
 func GetInstance(ctx context.Context, serviceID string, instanceID string) 
(*Instance, error) {
        domain := util.ParseDomain(ctx)
        project := util.ParseProject(ctx)
@@ -2927,6 +3019,18 @@ func GetInstancesByServiceID(ctx context.Context, 
serviceID string) ([]*discover
        return res, nil
 }
 
+func DeleteDependencyForDeleteService(domainProject string, serviceID string, 
service *discovery.MicroServiceKey) error {
+       conDep := new(discovery.ConsumerDependency)
+       conDep.Consumer = service
+       conDep.Providers = []*discovery.MicroServiceKey{}
+       conDep.Override = true
+       err := syncDependencyRule(context.TODO(), domainProject, conDep)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
 func formatRevision(consumerServiceID string, instances 
[]*discovery.MicroServiceInstance) (string, error) {
        if instances == nil {
                return fmt.Sprintf("%x", 
sha1.Sum(util.StringToBytesWithNoCopy(consumerServiceID))), nil
diff --git a/datasource/mongo/sd/types.go b/datasource/mongo/sd/types.go
index 881f27b..e5676e0 100644
--- a/datasource/mongo/sd/types.go
+++ b/datasource/mongo/sd/types.go
@@ -56,7 +56,13 @@ type MongoEventHandler interface {
 }
 
 func NewMongoEventByResource(resource *sdcommon.Resource, action 
discovery.EventType) MongoEvent {
-       return MongoEvent{ResourceID: resource.Key, DocumentID: 
resource.DocumentID, Value: resource.Value, Type: action}
+       return MongoEvent{
+               Type:       action,
+               Index:      resource.Index,
+               Value:      resource.Value,
+               ResourceID: resource.Key,
+               DocumentID: resource.DocumentID,
+       }
 }
 
 func NewMongoEvent(id string, documentID string, index string, action 
discovery.EventType, v interface{}) MongoEvent {

Reply via email to