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 a0a2104  [SCB-2094] add dep UT, implement dep query interface (#776)
a0a2104 is described below

commit a0a2104115578c3e1baa28e1970e8fdfedfc4c06
Author: xzccfzy <[email protected]>
AuthorDate: Tue Dec 15 10:01:12 2020 +0800

    [SCB-2094] add dep UT, implement dep query interface (#776)
---
 datasource/mongo/database.go         |   3 +
 datasource/mongo/dep.go              | 203 +--------------
 datasource/mongo/dep_test.go         | 484 ++++++++++++++++++++++++++---------
 datasource/mongo/dependency_query.go | 474 ++++++++++++++++++++++++++++++++++
 datasource/mongo/ms.go               |  58 +++--
 5 files changed, 877 insertions(+), 345 deletions(-)

diff --git a/datasource/mongo/database.go b/datasource/mongo/database.go
index 3bfdf25..9cbcfb5 100644
--- a/datasource/mongo/database.go
+++ b/datasource/mongo/database.go
@@ -76,6 +76,9 @@ const (
        ColumnRuleInfo       = "ruleinfo"
        ColumnInstanceInfo   = "instanceinfo"
        ColumnInstanceID     = "instanceid"
+       ColumnConsumerID     = "consumerid"
+       ColumnMongoID        = "_id"
+       ColumnTenant         = "tenant"
 )
 
 type Service struct {
diff --git a/datasource/mongo/dep.go b/datasource/mongo/dep.go
index 6a1eef2..0566c5b 100644
--- a/datasource/mongo/dep.go
+++ b/datasource/mongo/dep.go
@@ -19,13 +19,11 @@ package mongo
 
 import (
        "context"
+       "fmt"
 
        pb "github.com/go-chassis/cari/discovery"
        "go.mongodb.org/mongo-driver/bson"
 
-       "fmt"
-       "strings"
-
        "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/datasource/mongo/client"
        "github.com/apache/servicecomb-service-center/pkg/log"
@@ -33,6 +31,7 @@ import (
 )
 
 func (ds *DataSource) SearchProviderDependency(ctx context.Context, request 
*pb.GetDependenciesRequest) (*pb.GetProDependenciesResponse, error) {
+       domainProject := util.ParseDomainProject(ctx)
        providerServiceID := request.ServiceId
        filter := GeneratorServiceFilter(ctx, providerServiceID)
        provider, err := GetService(ctx, filter)
@@ -47,7 +46,8 @@ func (ds *DataSource) SearchProviderDependency(ctx 
context.Context, request *pb.
                }, nil
        }
 
-       services, err := GetDependencyProviders(ctx, provider.ServiceInfo, 
request)
+       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)
@@ -63,6 +63,7 @@ func (ds *DataSource) SearchProviderDependency(ctx 
context.Context, request *pb.
 }
 
 func (ds *DataSource) SearchConsumerDependency(ctx context.Context, request 
*pb.GetDependenciesRequest) (*pb.GetConDependenciesResponse, error) {
+       domainProject := util.ParseDomainProject(ctx)
        consumerID := request.ServiceId
 
        filter := GeneratorServiceFilter(ctx, consumerID)
@@ -78,7 +79,8 @@ func (ds *DataSource) SearchConsumerDependency(ctx 
context.Context, request *pb.
                }, nil
        }
 
-       services, err := GetDependencyProviders(ctx, consumer.ServiceInfo, 
request)
+       dr := NewConsumerDependencyRelation(ctx, domainProject, 
consumer.ServiceInfo)
+       services, err := 
dr.GetDependencyProviders(ToDependencyFilterOptions(request)...)
        if err != nil {
                log.Error(fmt.Sprintf("GetConsumerDependencies failed, consumer 
is %s/%s/%s/%s",
                        consumer.ServiceInfo.Environment, 
consumer.ServiceInfo.AppId, consumer.ServiceInfo.ServiceName, 
consumer.ServiceInfo.Version), err)
@@ -152,197 +154,6 @@ func (ds *DataSource) DeleteDependency() {
        panic("implement me")
 }
 
-func GetDependencyProviders(ctx context.Context, consumer *pb.MicroService, 
request *pb.GetDependenciesRequest) ([]*pb.MicroService, error) {
-       keys, err := GetProviderKeys(ctx, consumer)
-       if err != nil {
-               return nil, err
-       }
-
-       services := make([]*pb.MicroService, 0, len(keys))
-
-       for _, key := range keys {
-               domainProject := util.ParseDomainProject(ctx)
-               if request.SameDomain && key.Tenant != domainProject {
-                       continue
-               }
-
-               providerIDs, err := ParseDependencyRule(ctx, key)
-               if err != nil {
-                       return nil, err
-               }
-
-               if key.ServiceName == "*" {
-                       services = services[:0]
-               }
-
-               for _, providerID := range providerIDs {
-                       filter := GeneratorServiceFilter(ctx, providerID)
-                       provider, err := GetService(ctx, filter)
-                       if err != nil {
-                               log.Warn(fmt.Sprintf("get provider[%s/%s/%s/%s] 
failed",
-                                       key.Environment, key.AppId, 
key.ServiceName, key.Version))
-                               continue
-                       }
-                       if provider == nil {
-                               log.Warn(fmt.Sprintf("provider[%s/%s/%s/%s] 
does not exist",
-                                       key.Environment, key.AppId, 
key.ServiceName, key.Version))
-                               continue
-                       }
-                       if request.NoSelf && providerID == consumer.ServiceId {
-                               continue
-                       }
-                       services = append(services, provider.ServiceInfo)
-               }
-
-               if key.ServiceName == "*" {
-                       break
-               }
-       }
-
-       return services, nil
-}
-
-func GetProviderKeys(ctx context.Context, consumer *pb.MicroService) 
([]*pb.MicroServiceKey, error) {
-       if consumer == nil {
-               return nil, ErrInvalidConsumer
-       }
-       domainProject := util.ParseDomainProject(ctx)
-       consumerMicroServiceKey := &pb.MicroServiceKey{
-               Tenant:      domainProject,
-               Environment: consumer.Environment,
-               AppId:       consumer.AppId,
-               ServiceName: consumer.ServiceName,
-               Alias:       consumer.Alias,
-               Version:     consumer.Version,
-       }
-
-       filter := GenerateConsumerDependencyRuleKey(ctx, 
consumerMicroServiceKey)
-
-       findRes, err := client.GetMongoClient().Find(ctx, CollectionDep, filter)
-       if err != nil {
-               return nil, err
-       }
-       var services []*pb.MicroServiceKey
-       for findRes.Next(ctx) {
-               var tempMongoDep Dependency
-               err := findRes.Decode(&tempMongoDep)
-               if err != nil {
-                       return nil, err
-               }
-               providers := tempMongoDep.DependencyInfo.Providers
-               services = append(services, providers...)
-       }
-       return services, nil
-}
-
-func GenerateConsumerDependencyRuleKey(ctx context.Context, in 
*pb.MicroServiceKey) bson.M {
-
-       domain := util.ParseDomain(ctx)
-       project := util.ParseProject(ctx)
-       if in == nil {
-               return bson.M{
-                       ColumnDomain:  domain,
-                       ColumnProject: project,
-               }
-       }
-       if in.ServiceName == "*" {
-               return bson.M{
-                       ColumnDomain:  domain,
-                       ColumnProject: project,
-                       StringBuilder([]string{ColumnDependencyInfo, 
ColumnConsumer, ColumnEnv}): in.Environment,
-               }
-       }
-       return bson.M{
-               ColumnDomain:  domain,
-               ColumnProject: project,
-               StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, 
ColumnEnv}):     in.Environment,
-               StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, 
ColumnAppID}):   in.AppId,
-               StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, 
ColumnVersion}): in.Version,
-       }
-}
-
-func ParseDependencyRule(ctx context.Context, dependencyRule 
*pb.MicroServiceKey) (serviceIDs []string, err error) {
-       switch {
-       case dependencyRule.ServiceName == "*":
-               splited := strings.Split(dependencyRule.Tenant, "/")
-               filter := bson.M{
-                       ColumnDomain:  splited[0],
-                       ColumnProject: splited[1],
-                       StringBuilder([]string{ColumnServiceInfo, ColumnEnv}): 
dependencyRule.Environment}
-               findRes, err := client.GetMongoClient().Find(ctx, 
CollectionService, filter)
-               if err != nil {
-                       return nil, err
-               }
-               for findRes.Next(ctx) {
-                       var service Service
-                       err = findRes.Decode(&service)
-                       if err != nil {
-                               return nil, err
-                       }
-                       serviceIDs = append(serviceIDs, 
service.ServiceInfo.ServiceId)
-               }
-       default:
-               serviceIDs, err = FindServiceIds(ctx, dependencyRule)
-       }
-       return
-}
-
-func FindServiceIds(ctx context.Context, key *pb.MicroServiceKey) ([]string, 
error) {
-       versionRule := key.Version
-       splited := strings.Split(key.Tenant, "/")
-       if len(versionRule) == 0 {
-               return nil, nil
-       }
-       rangeIdx := strings.Index(versionRule, "-")
-       switch {
-       case versionRule == "latest":
-               filter := bson.M{
-                       ColumnDomain:  splited[0],
-                       ColumnProject: splited[1]}
-               return GetFilterVersionService(ctx, filter)
-       case versionRule[len(versionRule)-1:] == "+":
-               start := versionRule[:len(versionRule)-1]
-               filter := bson.M{
-                       ColumnDomain:  splited[0],
-                       ColumnProject: splited[1],
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnVersion}): bson.M{"$gte": start}}
-               return GetFilterVersionService(ctx, filter)
-       case rangeIdx > 0:
-               start := versionRule[:rangeIdx]
-               end := versionRule[rangeIdx+1:]
-               filter := bson.M{
-                       ColumnDomain:  splited[0],
-                       ColumnProject: splited[1],
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnVersion}): bson.M{"$gts": start, "$lt": end}}
-               return GetFilterVersionService(ctx, filter)
-       default:
-               filter := bson.M{
-                       ColumnDomain:  splited[0],
-                       ColumnProject: splited[1],
-                       StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):  
       key.Environment,
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnAppID}):       key.AppId,
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnServiceName}): key.ServiceName,
-                       StringBuilder([]string{ColumnServiceInfo, 
ColumnVersion}):     key.Version}
-               return GetFilterVersionService(ctx, filter)
-       }
-}
-
-func GetFilterVersionService(ctx context.Context, m bson.M) (serviceIDs 
[]string, err error) {
-       findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m)
-       if err != nil {
-               return nil, err
-       }
-       for findRes.Next(ctx) {
-               var service Service
-               err = findRes.Decode(&service)
-               if err != nil {
-                       return nil, err
-               }
-               serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
-       }
-       return
-}
-
 func GetServiceID(ctx context.Context, key *pb.MicroServiceKey) (serviceID 
string, err error) {
        domain := util.ParseDomain(ctx)
        project := util.ParseProject(ctx)
diff --git a/datasource/mongo/dep_test.go b/datasource/mongo/dep_test.go
index 77bdc06..2b0f4fb 100644
--- a/datasource/mongo/dep_test.go
+++ b/datasource/mongo/dep_test.go
@@ -25,182 +25,237 @@ import (
        "github.com/stretchr/testify/assert"
 )
 
-func TestDep_Creat(t *testing.T) {
-
+func Test_Creat(t *testing.T) {
        var (
                consumerId1 string
+               consumerId2 string
                consumerId3 string
        )
 
-       t.Run("creat service, when request is valid, should not pass", func(t 
*testing.T) {
-               respCreateService, err := 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+       t.Run("create service, should be passed", func(t *testing.T) {
+               resp, err := 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep1",
-                               AppId:       "create_dep_group",
-                               ServiceName: "create_dep_consumer",
+                               AppId:       "dep_create_dep_group",
+                               ServiceName: "dep_create_dep_consumer",
                                Version:     "1.0.0",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
-               consumerId1 = respCreateService.ServiceId
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+               consumerId1 = resp.ServiceId
 
-               respCreateService, err = 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep2",
-                               AppId:       "create_dep_group",
-                               ServiceName: "create_dep_consumer_all",
+                               AppId:       "dep_create_dep_group",
+                               ServiceName: "dep_create_dep_consumer_all",
                                Version:     "1.0.0",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
-               consumerId3 = respCreateService.ServiceId
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+               consumerId3 = resp.ServiceId
 
-               respCreateService, err = 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep3",
                                Environment: pb.ENV_PROD,
-                               AppId:       "create_dep_group",
-                               ServiceName: "create_dep_consumer",
+                               AppId:       "dep_create_dep_group",
+                               ServiceName: "dep_create_dep_consumer",
                                Version:     "1.0.0",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+               consumerId2 = resp.ServiceId
 
-               respCreateService, err = 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep4",
-                               AppId:       "create_dep_group",
-                               ServiceName: "create_dep_provider",
+                               AppId:       "dep_create_dep_group",
+                               ServiceName: "dep_create_dep_provider",
                                Version:     "1.0.0",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-               respCreateService, err = 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep5",
-                               AppId:       "create_dep_group",
-                               ServiceName: "create_dep_provider",
+                               AppId:       "dep_create_dep_group",
+                               ServiceName: "dep_create_dep_provider",
                                Version:     "1.0.1",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-               respCreateService, err = 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep6",
                                Environment: pb.ENV_PROD,
-                               AppId:       "create_dep_group",
-                               ServiceName: "create_dep_provider",
+                               AppId:       "dep_create_dep_group",
+                               ServiceName: "dep_create_dep_provider",
                                Version:     "1.0.0",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
        })
 
-       t.Run("create dep, when request is valid, should be passed", func(t 
*testing.T) {
+       t.Run("add dep and search, when request is invalid, should be failed", 
func(t *testing.T) {
+               consumer := &pb.MicroServiceKey{
+                       AppId:       "dep_create_dep_group",
+                       ServiceName: "dep_create_dep_consumer",
+                       Version:     "1.0.0",
+               }
+               providers := []*pb.MicroServiceKey{
+                       {
+                               AppId:       "dep_create_dep_group",
+                               ServiceName: "dep_create_dep_provider",
+                               Version:     "1.0.0",
+                       },
+               }
 
-               respCreateDependency, err := 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               // consumer does not exist
+               resp, err := 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: &pb.MicroServiceKey{
-                                       ServiceName: "create_dep_consumer",
-                                       AppId:       "create_dep_group",
+                                       AppId:       "noexistapp",
+                                       ServiceName: "noexistservice",
                                        Version:     "1.0.0",
                                },
+                               Providers: providers,
+                       },
+               }, false)
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ErrServiceNotExists, resp.GetCode())
+
+               // provider in diff env
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+                       {
+                               Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
                                        {
-                                               AppId:       "create_dep_group",
-                                               ServiceName: 
"create_dep_provider",
+                                               Environment: pb.ENV_PROD,
+                                               AppId:       
"dep_service_group_provider",
+                                               ServiceName: 
"dep_service_name_provider",
                                                Version:     "latest",
                                        },
                                },
                        },
                }, false)
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateDependency.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respPro, err := 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               // consumer in diff env
+               consumer.Environment = pb.ENV_PROD
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+                       {
+                               Consumer: consumer,
+                               Providers: []*pb.MicroServiceKey{
+                                       {
+                                               AppId:       
"dep_service_group_provider",
+                                               ServiceName: 
"dep_service_name_provider",
+                                               Version:     "latest",
+                                       },
+                               },
+                       },
+               }, false)
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+               respCon, err := 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
+               assert.NotNil(t, respCon)
+               assert.NoError(t, err)
+
+               respCon, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+                       ServiceId: consumerId2,
+               })
+               assert.NotNil(t, respCon)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-               assert.NotEqual(t, "1.0.1", respPro.Providers[0].Version)
+       })
+
+       t.Run("add dep and search, when request is valid, should be passed", 
func(t *testing.T) {
+               consumer := &pb.MicroServiceKey{
+                       ServiceName: "dep_create_dep_consumer",
+                       AppId:       "dep_create_dep_group",
+                       Version:     "1.0.0",
+               }
 
-               respCreateDependency, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               // add latest
+               resp, err := 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
                        {
-                               Consumer: &pb.MicroServiceKey{
-                                       ServiceName: "create_dep_consumer",
-                                       AppId:       "create_dep_group",
-                                       Version:     "1.0.0",
-                               },
+                               Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
                                        {
-                                               AppId:       "create_dep_group",
-                                               ServiceName: 
"create_dep_provider",
-                                               Version:     "1.0.0+",
+                                               AppId:       
"dep_create_dep_group",
+                                               ServiceName: 
"dep_create_dep_provider",
+                                               Version:     "latest",
                                        },
                                },
                        },
                }, false)
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateDependency.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               respPro, err := 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
+               assert.NotNil(t, respPro)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-               assert.NotEqual(t, "1.0.1", respPro.Providers[0].Version)
+               assert.NotEqual(t, 0, len(respPro.Providers))
+               assert.Equal(t, "1.0.1", respPro.Providers[0].Version)
 
-               respCreateDependency, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               // add 1.0.0+
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
                        {
-                               Consumer: &pb.MicroServiceKey{
-                                       ServiceName: "create_dep_consumer",
-                                       AppId:       "create_dep_group",
-                                       Version:     "1.0.0",
-                               },
+                               Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
                                        {
-                                               AppId:       "create_dep_group",
-                                               ServiceName: 
"create_dep_provider",
+                                               AppId:       
"dep_create_dep_group",
+                                               ServiceName: 
"dep_create_dep_provider",
                                                Version:     "1.0.0+",
                                        },
                                },
                        },
                }, false)
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateDependency.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
                respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
+               assert.NotNil(t, respPro)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-               assert.NotEqual(t, 2, len(respPro.Providers))
 
-               respCreateDependency, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               // add *
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: &pb.MicroServiceKey{
-                                       ServiceName: "create_dep_consumer_all",
-                                       AppId:       "create_dep_group",
+                                       ServiceName: 
"dep_create_dep_consumer_all",
+                                       AppId:       "dep_create_dep_group",
                                        Version:     "1.0.0",
                                },
                                Providers: []*pb.MicroServiceKey{
@@ -210,40 +265,40 @@ func TestDep_Creat(t *testing.T) {
                                },
                        },
                }, false)
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateDependency.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
                respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId3,
                })
+               assert.NotNil(t, respPro)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-               assert.NotEqual(t, 0, len(respPro.Providers))
+               assert.Equal(t, 0, len(respPro.Providers))
 
-               respCreateDependency, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               // clean all
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
                        {
                                Consumer: &pb.MicroServiceKey{
-                                       ServiceName: "create_dep_consumer_all",
-                                       AppId:       "create_dep_group",
+                                       ServiceName: 
"dep_create_dep_consumer_all",
+                                       AppId:       "dep_create_dep_group",
                                        Version:     "1.0.0",
                                },
                                Providers: nil,
                        },
                }, false)
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateDependency.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respCreateDependency, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               // add multiple providers
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
                        {
-                               Consumer: &pb.MicroServiceKey{
-                                       ServiceName: "create_dep_consumer",
-                                       AppId:       "create_dep_group",
-                                       Version:     "1.0.0",
-                               },
+                               Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
                                        {
-                                               AppId:       "create_dep_group",
-                                               ServiceName: 
"create_dep_provider",
+                                               AppId:       
"dep_create_dep_group",
+                                               ServiceName: 
"dep_create_dep_provider",
                                                Version:     "1.0.0",
                                        },
                                        {
@@ -252,100 +307,281 @@ func TestDep_Creat(t *testing.T) {
                                },
                        },
                }, false)
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateDependency.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-               respCreateDependency, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+               // add 1.0.0-2.0.0 to override *
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
                        {
-                               Consumer: &pb.MicroServiceKey{
-                                       ServiceName: "create_dep_consumer",
-                                       AppId:       "create_dep_group",
-                                       Version:     "1.0.0",
-                               },
+                               Consumer: consumer,
                                Providers: []*pb.MicroServiceKey{
                                        {
-                                               AppId:       "create_dep_group",
-                                               ServiceName: 
"create_dep_provider",
+                                               AppId:       
"dep_create_dep_group",
+                                               ServiceName: 
"dep_create_dep_provider",
                                                Version:     "1.0.0-1.0.1",
                                        },
                                },
                        },
                }, false)
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+               respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+                       ServiceId: consumerId1,
+               })
+               assert.NotNil(t, respPro)
+               assert.NoError(t, err)
+               assert.Equal(t, "1.0.1", respPro.Providers[0].Version)
+
+               // add not override
+               respAdd, err := 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+                       {
+                               Consumer: consumer,
+                               Providers: []*pb.MicroServiceKey{
+                                       {
+                                               AppId:       
"dep_create_dep_group",
+                                               ServiceName: 
"dep_create_dep_provider",
+                                               Version:     "1.0.0-3.0.0",
+                                       },
+                               },
+                       },
+               }, false)
+               assert.NotNil(t, respAdd)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, respAdd.GetCode())
+
+               respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+                       ServiceId: consumerId1,
+               })
+               assert.NotNil(t, respPro)
+               assert.NoError(t, err)
+
+               // add provider is empty
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+                       {
+                               Consumer:  consumer,
+                               Providers: []*pb.MicroServiceKey{},
+                       },
+               }, false)
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+               resp, err = 
datasource.Instance().AddOrUpdateDependencies(getContext(), 
[]*pb.ConsumerDependency{
+                       {
+                               Consumer: consumer,
+                       },
+               }, false)
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateDependency.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
                respPro, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
                })
+               assert.NotNil(t, respPro)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-               assert.Equal(t, "1.0.0", respPro.Providers[0].Version)
        })
 }
 
-func TestDep_Get(t *testing.T) {
-
+func Test_Get(t *testing.T) {
        var (
                consumerId1 string
                providerId1 string
+               providerId2 string
        )
 
-       t.Run("create service, when request is valid, should be passed", func(t 
*testing.T) {
-               respCreateService, err := 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+       t.Run("create service, should be passed", func(t *testing.T) {
+               resp, err := 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep7",
-                               AppId:       "get_dep_group",
-                               ServiceName: "get_dep_consumer",
+                               AppId:       "dep_get_dep_group",
+                               ServiceName: "dep_get_dep_consumer",
                                Version:     "1.0.0",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
-               consumerId1 = respCreateService.ServiceId
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+               consumerId1 = resp.ServiceId
 
-               respCreateService, err = 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep8",
-                               AppId:       "get_dep_group",
-                               ServiceName: "get_dep_provider",
+                               AppId:       "dep_get_dep_group",
+                               ServiceName: "dep_get_dep_provider",
                                Version:     "1.0.0",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
-               providerId1 = respCreateService.ServiceId
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+               providerId1 = resp.ServiceId
 
-               respCreateService, err = 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+               resp, err = datasource.Instance().RegisterService(getContext(), 
&pb.CreateServiceRequest{
                        Service: &pb.MicroService{
-                               ServiceId:   "dep9",
-                               AppId:       "get_dep_group",
-                               ServiceName: "get_dep_provider",
+                               AppId:       "dep_get_dep_group",
+                               ServiceName: "dep_get_dep_provider",
                                Version:     "2.0.0",
                                Level:       "FRONT",
                                Status:      pb.MS_UP,
                        },
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, 
respCreateService.Response.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+               providerId2 = resp.ServiceId
        })
 
-       t.Run("execute 'search dep' operation, when request is valid,should be 
passed", func(t *testing.T) {
-               respPro, err := 
datasource.Instance().SearchProviderDependency(getContext(), 
&pb.GetDependenciesRequest{
+       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{
                        ServiceId: providerId1,
                })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
 
-               respCon, err := 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+               //get consumer
+               resp, err = 
datasource.Instance().SearchProviderDependency(getContext(), 
&pb.GetDependenciesRequest{
+                       ServiceId: consumerId1,
+               })
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+       })
+
+       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{
+                       ConsumerServiceId: consumerId1,
+                       AppId:             "dep_get_dep_group",
+                       ServiceName:       "dep_get_dep_provider",
+                       VersionRule:       "1.0.0+",
+               })
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+               // get consumer's deps
+               respGetP, err := 
datasource.Instance().SearchProviderDependency(getContext(), 
&pb.GetDependenciesRequest{
+                       ServiceId: providerId1,
+               })
+               assert.NotNil(t, respGetP)
+               assert.NoError(t, err)
+
+               // get provider's deps
+               respGetC, err := 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+                       ServiceId: consumerId1,
+               })
+               assert.NotNil(t, respGetC)
+               assert.NoError(t, err)
+
+               // get self deps
+               resp, err = datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+                       ConsumerServiceId: consumerId1,
+                       AppId:             "dep_get_dep_group",
+                       ServiceName:       "dep_get_dep_consumer",
+                       VersionRule:       "1.0.0+",
+               })
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+               respGetC, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
                        ServiceId: consumerId1,
+                       NoSelf:    true,
+               })
+               assert.NotNil(t, respGetC)
+               assert.NoError(t, err)
+
+               // find before provider register
+               resp, err = datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+                       ConsumerServiceId: providerId2,
+                       AppId:             "dep_get_dep_group",
+                       ServiceName:       "dep_get_dep_finder",
+                       VersionRule:       "1.0.0+",
+               })
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+
+               respCreateF, err := 
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+                       Service: &pb.MicroService{
+                               AppId:       "dep_get_dep_group",
+                               ServiceName: "dep_get_dep_finder",
+                               Version:     "1.0.0",
+                               Level:       "FRONT",
+                               Status:      pb.MS_UP,
+                       },
+               })
+               assert.NotNil(t, respCreateF)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, 
respCreateF.Response.GetCode())
+               finder1 := respCreateF.ServiceId
+
+               resp, err = datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+                       ConsumerServiceId: providerId2,
+                       AppId:             "dep_get_dep_group",
+                       ServiceName:       "dep_get_dep_finder",
+                       VersionRule:       "1.0.0+",
+               })
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+               respGetC, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+                       ServiceId: providerId2,
+               })
+               assert.NotNil(t, respGetC)
+               assert.NoError(t, err)
+
+               // find after delete micro service
+               respDelP, err := 
datasource.Instance().UnregisterService(getContext(), &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{
+                       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{
+                       Service: &pb.MicroService{
+                               ServiceId:   finder1,
+                               AppId:       "dep_get_dep_group",
+                               ServiceName: "dep_get_dep_finder",
+                               Version:     "1.0.0",
+                               Level:       "FRONT",
+                               Status:      pb.MS_UP,
+                       },
                })
+               assert.NotNil(t, respCreateF)
+               assert.NoError(t, err)
+               assert.Equal(t, pb.ResponseSuccess, 
respCreateF.Response.GetCode())
 
+               resp, err = datasource.Instance().FindInstances(getContext(), 
&pb.FindInstancesRequest{
+                       ConsumerServiceId: providerId2,
+                       AppId:             "dep_get_dep_group",
+                       ServiceName:       "dep_get_dep_finder",
+                       VersionRule:       "1.0.0+",
+               })
+               assert.NotNil(t, resp)
                assert.NoError(t, err)
-               assert.Equal(t, pb.ResponseSuccess, respCon.Response.GetCode())
+               assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
+               respGetC, err = 
datasource.Instance().SearchConsumerDependency(getContext(), 
&pb.GetDependenciesRequest{
+                       ServiceId: providerId2,
+               })
+               assert.NotNil(t, respGetC)
+               assert.NoError(t, err)
+               assert.Equal(t, 0, len(respGetC.Providers))
        })
 }
diff --git a/datasource/mongo/dependency_query.go 
b/datasource/mongo/dependency_query.go
new file mode 100644
index 0000000..8025aba
--- /dev/null
+++ b/datasource/mongo/dependency_query.go
@@ -0,0 +1,474 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mongo
+
+import (
+       "context"
+       "fmt"
+       "strings"
+
+       "github.com/apache/servicecomb-service-center/datasource/mongo/client"
+       "github.com/apache/servicecomb-service-center/pkg/log"
+       pb "github.com/go-chassis/cari/discovery"
+       "go.mongodb.org/mongo-driver/bson"
+       "go.mongodb.org/mongo-driver/mongo/options"
+)
+
+type DependencyRelation struct {
+       ctx           context.Context
+       domainProject string
+       consumer      *pb.MicroService
+       provider      *pb.MicroService
+}
+
+type DependencyRelationFilterOpt struct {
+       SameDomainProject bool
+       NonSelf           bool
+}
+
+type DependencyRelationFilterOption func(opt DependencyRelationFilterOpt) 
DependencyRelationFilterOpt
+
+func NewConsumerDependencyRelation(ctx context.Context, domainProject string, 
consumer *pb.MicroService) *DependencyRelation {
+       return NewDependencyRelation(ctx, domainProject, consumer, nil)
+}
+
+func NewProviderDependencyRelation(ctx context.Context, domainProject string, 
provider *pb.MicroService) *DependencyRelation {
+       return NewDependencyRelation(ctx, domainProject, nil, provider)
+}
+
+func NewDependencyRelation(ctx context.Context, domainProject string, consumer 
*pb.MicroService, provider *pb.MicroService) *DependencyRelation {
+       return &DependencyRelation{
+               ctx:           ctx,
+               domainProject: domainProject,
+               consumer:      consumer,
+               provider:      provider,
+       }
+}
+
+func (dr *DependencyRelation) GetDependencyProviders(opts 
...DependencyRelationFilterOption) ([]*pb.MicroService, error) {
+       keys, err := dr.getProviderKeys()
+       if err != nil {
+               return nil, err
+       }
+       services := make([]*pb.MicroService, 0, len(keys))
+       op := ToDependencyRelationFilterOpt(opts...)
+
+       for _, key := range keys {
+               if op.SameDomainProject && key.Tenant != dr.domainProject {
+                       continue
+               }
+               providerIDs, err := dr.parseDependencyRule(key)
+
+               if err != nil {
+                       return nil, err
+               }
+
+               if key.ServiceName == "*" {
+                       services = services[:0]
+               }
+
+               for _, providerID := range providerIDs {
+                       filter := GeneratorServiceFilter(dr.ctx, providerID)
+                       provider, err := GetService(dr.ctx, filter)
+                       if err != nil {
+                               log.Warn(fmt.Sprintf("get provider[%s/%s/%s/%s] 
failed",
+                                       key.Environment, key.AppId, 
key.ServiceName, key.Version))
+                               continue
+                       }
+                       if provider == nil {
+                               log.Warn(fmt.Sprintf("provider[%s/%s/%s/%s] 
does not exist",
+                                       key.Environment, key.AppId, 
key.ServiceName, key.Version))
+                               continue
+                       }
+                       if op.NonSelf && providerID == dr.consumer.ServiceId {
+                               continue
+                       }
+                       services = append(services, provider.ServiceInfo)
+               }
+               if key.ServiceName == "*" {
+                       break
+               }
+       }
+       return services, nil
+}
+
+func (dr *DependencyRelation) GetDependencyConsumers(opts 
...DependencyRelationFilterOption) ([]*pb.MicroService, error) {
+       consumerDependAllList, err := dr.GetDependencyConsumersOfProvider()
+       if err != nil {
+               log.Error(fmt.Sprintf("get service[%s]'s consumers failed", 
dr.provider.ServiceId), err)
+               return nil, err
+       }
+       consumers := make([]*pb.MicroService, 0)
+       op := ToDependencyRelationFilterOpt(opts...)
+       for _, consumer := range consumerDependAllList {
+               if op.SameDomainProject && consumer.Tenant != dr.domainProject {
+                       continue
+               }
+               service, err := dr.GetServiceByMicroServiceKey(consumer)
+               if err != nil {
+                       return nil, err
+               }
+               if service == nil {
+                       log.Warn(fmt.Sprintf("consumer[%s/%s/%s/%s] does not 
exist",
+                               consumer.Environment, consumer.AppId, 
consumer.ServiceName, consumer.Version))
+                       continue
+               }
+               if op.NonSelf && service.ServiceId == dr.provider.ServiceId {
+                       continue
+               }
+               consumers = append(consumers, service)
+       }
+       return consumers, nil
+}
+
+func (dr *DependencyRelation) GetDependencyConsumersOfProvider() 
([]*pb.MicroServiceKey, error) {
+       if dr.provider == nil {
+               return nil, ErrInvalidConsumer
+       }
+       consumerDependAllList, err := dr.getConsumerOfDependAllServices()
+       if err != nil {
+               log.Error(fmt.Sprintf("get consumers that depend on all 
services failed, %s", dr.provider.ServiceId), err)
+               return nil, err
+       }
+       return consumerDependAllList, nil
+}
+
+func (dr *DependencyRelation) GetServiceByMicroServiceKey(service 
*pb.MicroServiceKey) (*pb.MicroService, error) {
+       filter, err := MicroServiceKeyFilter(service)
+       if err != nil {
+               log.Error("get serivce failed", err)
+               return nil, err
+       }
+       findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionService, 
filter)
+       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)
+               if err != nil {
+                       return nil, err
+               }
+               if service.ServiceInfo != nil {
+                       return service.ServiceInfo, nil
+               }
+       }
+       return nil, nil
+}
+
+func (dr *DependencyRelation) getConsumerOfDependAllServices() 
([]*pb.MicroServiceKey, error) {
+       providerService := pb.MicroServiceToKey(dr.domainProject, dr.provider)
+       providerService.ServiceName = "*"
+       filter := GenerateProviderDependencyRuleKey(dr.domainProject, 
dr.provider.ServiceId, providerService)
+       findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionDep, 
filter)
+       if err != nil {
+               return nil, err
+       }
+       if findRes.Err() != nil {
+               return nil, findRes.Err()
+       }
+
+       var msKeys []*pb.MicroServiceKey
+       for findRes.Next(dr.ctx) {
+               var dep *Dependency
+               err = findRes.Decode(&dep)
+               if err != nil {
+                       return nil, err
+               }
+               msKeys = append(msKeys, dep.DependencyInfo.Consumer)
+       }
+       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)
+       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)
+               if err != nil {
+                       return nil, err
+               }
+               if dep != nil {
+                       break
+               }
+       }
+       if dep != nil {
+               return dep.DependencyInfo.Providers, nil
+       }
+       return nil, nil
+}
+
+func (dr *DependencyRelation) parseDependencyRule(dependencyRule 
*pb.MicroServiceKey) (serviceIDs []string, err error) {
+       switch {
+       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)
+               if err != nil {
+                       log.Error("get serivce failed", err)
+                       return nil, err
+               }
+               findRes, err := client.GetMongoClient().Find(dr.ctx, 
CollectionService, filter)
+               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)
+                       if err != nil {
+                               return nil, err
+                       }
+                       serviceIDs = append(serviceIDs, 
service.ServiceInfo.ServiceId)
+               }
+       default:
+               serviceIDs, _, err = FindServiceIds(dr.ctx, 
dependencyRule.Version, dependencyRule)
+       }
+       return
+}
+
+func (dr *DependencyRelation) GetDependencyConsumerIds() ([]string, error) {
+       consumerDependAllList, err := dr.GetDependencyConsumersOfProvider()
+       if err != nil {
+               return nil, err
+       }
+       consumerIDs := make([]string, 0, len(consumerDependAllList))
+       for _, consumer := range consumerDependAllList {
+               consumerID, err := GetServiceID(dr.ctx, consumer)
+               if err != nil {
+                       log.Error(fmt.Sprintf("get consumer[%s/%s/%s/%s] 
failed",
+                               consumer.Environment, consumer.AppId, 
consumer.ServiceName, consumer.Version), err)
+                       return nil, err
+               }
+               if len(consumerID) == 0 {
+                       log.Warn(fmt.Sprintf("get consumer[%s/%s/%s/%s] not 
exist",
+                               consumer.Environment, consumer.AppId, 
consumer.ServiceName, consumer.Version))
+                       continue
+               }
+               consumerIDs = append(consumerIDs, consumerID)
+       }
+       return consumerIDs, nil
+}
+
+func MicroServiceKeyFilter(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,
+               StringBuilder([]string{ColumnServiceInfo, ColumnAppID}):   
key.AppId,
+               StringBuilder([]string{ColumnServiceInfo, ColumnAlias}):   
key.Alias,
+               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 {
+               return nil, false, ErrInvalidDomainProject
+       }
+       if match == nil {
+               tenant := strings.Split(key.Tenant, "/")
+               if len(tenant) != 2 {
+                       return nil, false, ErrInvalidDomainProject
+               }
+               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 {
+                       return nil, false, nil
+               }
+               if findRes.Err() != nil {
+                       return nil, false, findRes.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, false, nil
+       }
+       return match, false, nil
+}
+
+func ParseVersionRule(ctx context.Context, versionRule string, key 
*pb.MicroServiceKey) ([]string, error) {
+       tenant := strings.Split(key.Tenant, "/")
+       if len(tenant) != 2 {
+               return nil, ErrInvalidDomainProject
+       }
+       if len(versionRule) == 0 {
+               return nil, nil
+       }
+
+       rangeIdx := strings.Index(versionRule, "-")
+       switch {
+       case versionRule == "latest":
+               filter := bson.M{
+                       ColumnDomain:  tenant[0],
+                       ColumnProject: tenant[1]}
+               return GetFilterVersionServiceLatest(ctx, filter)
+       case versionRule[len(versionRule)-1:] == "+":
+               start := versionRule[:len(versionRule)-1]
+               filter := bson.M{
+                       ColumnDomain:  tenant[0],
+                       ColumnProject: tenant[1],
+                       StringBuilder([]string{ColumnServiceInfo, 
ColumnVersion}): bson.M{"$gte": start}}
+               return GetFilterVersionService(ctx, filter)
+       case rangeIdx > 0:
+               start := versionRule[:rangeIdx]
+               end := versionRule[rangeIdx+1:]
+               filter := bson.M{
+                       ColumnDomain:  tenant[0],
+                       ColumnProject: tenant[1],
+                       StringBuilder([]string{ColumnServiceInfo, 
ColumnVersion}): bson.M{"$gte": start, "$lte": end}}
+               return GetFilterVersionService(ctx, filter)
+       default:
+               return nil, nil
+       }
+}
+
+func GetFilterVersionService(ctx context.Context, m bson.M) (serviceIDs 
[]string, err error) {
+       findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m)
+       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 nil, err
+               }
+               serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
+       }
+       return
+}
+
+func GetFilterVersionServiceLatest(ctx context.Context, m bson.M) (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 nil, err
+               }
+               serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
+               if serviceIDs != nil {
+                       return serviceIDs, nil
+               }
+       }
+       return
+}
+
+func WithSameDomainProject() DependencyRelationFilterOption {
+       return func(opt DependencyRelationFilterOpt) 
DependencyRelationFilterOpt {
+               opt.SameDomainProject = true
+               return opt
+       }
+}
+func WithoutSelfDependency() DependencyRelationFilterOption {
+       return func(opt DependencyRelationFilterOpt) 
DependencyRelationFilterOpt {
+               opt.NonSelf = true
+               return opt
+       }
+}
+
+func ToDependencyFilterOptions(in *pb.GetDependenciesRequest) (opts 
[]DependencyRelationFilterOption) {
+       if in.SameDomain {
+               opts = append(opts, WithSameDomainProject())
+       }
+       if in.NoSelf {
+               opts = append(opts, WithoutSelfDependency())
+       }
+       return opts
+}
+
+func ToDependencyRelationFilterOpt(opts ...DependencyRelationFilterOption) (op 
DependencyRelationFilterOpt) {
+       for _, opt := range opts {
+               op = opt(op)
+       }
+       return
+}
+
+func GenerateConsumerDependencyRuleKey(domainProject string, serviceID string, 
in *pb.MicroServiceKey) bson.M {
+       return GenerateServiceDependencyRuleKey(domainProject, serviceID, in)
+}
+
+func GenerateProviderDependencyRuleKey(domainProject string, serviceID string, 
in *pb.MicroServiceKey) bson.M {
+       return GenerateServiceDependencyRuleKey(domainProject, serviceID, in)
+}
+
+func GenerateServiceDependencyRuleKey(domainProject string, serviceID string, 
in *pb.MicroServiceKey) bson.M {
+       if in == nil {
+               return bson.M{
+                       ColumnConsumerID: serviceID,
+                       StringBuilder([]string{ColumnDependencyInfo, 
ColumnConsumer, 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}
+       }
+       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}
+}
diff --git a/datasource/mongo/ms.go b/datasource/mongo/ms.go
index 46811ee..106cfca 100644
--- a/datasource/mongo/ms.go
+++ b/datasource/mongo/ms.go
@@ -1470,15 +1470,17 @@ func (ds *DataSource) GetInstance(ctx context.Context, 
request *discovery.GetOne
                                fmt.Sprintf("Provider[%s] does not exist.", 
request.ProviderServiceId)),
                }, nil
        }
-       findFlag := fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find 
provider[%s][%s/%s/%s/%s] instance[%s]",
-               request.ConsumerServiceId, service.ServiceInfo.Environment, 
service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, 
service.ServiceInfo.Version,
-               provider.ServiceInfo.ServiceId, 
provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, 
provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version,
-               request.ProviderInstanceId)
+       findFlag := func() string {
+               return fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find 
provider[%s][%s/%s/%s/%s] instance[%s]",
+                       request.ConsumerServiceId, 
service.ServiceInfo.Environment, service.ServiceInfo.AppId, 
service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+                       provider.ServiceInfo.ServiceId, 
provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, 
provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version,
+                       request.ProviderInstanceId)
+       }
 
        domainProject := util.ParseDomainProject(ctx)
        services, err := findServices(ctx, 
discovery.MicroServiceToKey(domainProject, provider.ServiceInfo))
        if err != nil {
-               log.Error(fmt.Sprintf("get instance failed %s", findFlag), err)
+               log.Error(fmt.Sprintf("get instance failed %s", findFlag()), 
err)
                return &discovery.GetOneInstanceResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
@@ -1487,7 +1489,7 @@ func (ds *DataSource) GetInstance(ctx context.Context, 
request *discovery.GetOne
                serviceIDs = filterServiceIDs(ctx, request.ConsumerServiceId, 
request.Tags, services)
        }
        if services == nil || len(serviceIDs) == 0 {
-               mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag)
+               mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag())
                log.Error("get instance failed", mes)
                return &discovery.GetOneInstanceResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1495,7 +1497,7 @@ func (ds *DataSource) GetInstance(ctx context.Context, 
request *discovery.GetOne
        }
        instances, err := instancesFilter(ctx, serviceIDs)
        if len(instances) == 0 {
-               mes := fmt.Errorf("%s failed, provider instance does not 
exist", findFlag)
+               mes := fmt.Errorf("%s failed, provider instance does not 
exist", findFlag())
                log.Error("get instance failed", err)
                return &discovery.GetOneInstanceResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInstanceNotExists, mes.Error()),
@@ -1551,13 +1553,15 @@ func (ds *DataSource) GetInstances(ctx context.Context, 
request *discovery.GetIn
                }, nil
        }
 
-       findFlag := fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find 
provider[%s][%s/%s/%s/%s] instances",
-               request.ConsumerServiceId, service.ServiceInfo.Environment, 
service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, 
service.ServiceInfo.Version,
-               provider.ServiceInfo.ServiceId, 
provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, 
provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version)
+       findFlag := func() string {
+               return fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find 
provider[%s][%s/%s/%s/%s] instances",
+                       request.ConsumerServiceId, 
service.ServiceInfo.Environment, service.ServiceInfo.AppId, 
service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+                       provider.ServiceInfo.ServiceId, 
provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, 
provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version)
+       }
 
        services, err := findServices(ctx, 
discovery.MicroServiceToKey(domainProject, provider.ServiceInfo))
        if err != nil {
-               log.Error(fmt.Sprintf("get instances failed %s", findFlag), err)
+               log.Error(fmt.Sprintf("get instances failed %s", findFlag()), 
err)
                return &discovery.GetInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
@@ -1566,7 +1570,7 @@ func (ds *DataSource) GetInstances(ctx context.Context, 
request *discovery.GetIn
                serviceIDs = filterServiceIDs(ctx, request.ConsumerServiceId, 
request.Tags, services)
        }
        if services == nil || len(serviceIDs) == 0 {
-               mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag)
+               mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag())
                log.Error("get instances failed", mes)
                return &discovery.GetInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1574,7 +1578,7 @@ func (ds *DataSource) GetInstances(ctx context.Context, 
request *discovery.GetIn
        }
        instances, err := instancesFilter(ctx, serviceIDs)
        if err != nil {
-               log.Error(fmt.Sprintf("get instances failed %s", findFlag), err)
+               log.Error(fmt.Sprintf("get instances failed %s", findFlag()), 
err)
                return &discovery.GetInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
@@ -1924,16 +1928,18 @@ func (ds *DataSource) findSharedServiceInstance(ctx 
context.Context, request *di
        var err error
        // it means the shared micro-services must be the same env with SC.
        provider.Environment = apt.Service.Environment
-       findFlag := fmt.Sprintf("find shared provider[%s/%s/%s/%s]", 
provider.Environment, provider.AppId, provider.ServiceName, provider.Version)
+       findFlag := func() string {
+               return fmt.Sprintf("find shared provider[%s/%s/%s/%s]", 
provider.Environment, provider.AppId, provider.ServiceName, provider.Version)
+       }
        services, err := findServices(ctx, provider)
        if err != nil {
-               log.Error(fmt.Sprintf("find shared service instance failed %s", 
findFlag), err)
+               log.Error(fmt.Sprintf("find shared service instance failed %s", 
findFlag()), err)
                return &discovery.FindInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
        }
        if services == nil {
-               mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag)
+               mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag())
                log.Error("find shared service instance failed", mes)
                return &discovery.FindInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1948,7 +1954,7 @@ func (ds *DataSource) findSharedServiceInstance(ctx 
context.Context, request *di
        }
        instances, err := instancesFilter(ctx, serviceIDs)
        if err != nil {
-               log.Error(fmt.Sprintf("find shared service instance failed %s", 
findFlag), err)
+               log.Error(fmt.Sprintf("find shared service instance failed %s", 
findFlag()), err)
                return &discovery.FindInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
@@ -1989,18 +1995,20 @@ func (ds *DataSource) findInstance(ctx context.Context, 
request *discovery.FindI
        ctx = util.SetTargetDomainProject(ctx, util.ParseDomain(ctx), 
util.ParseProject(ctx))
        provider.Tenant = util.ParseTargetDomainProject(ctx)
 
-       findFlag := fmt.Sprintf("Consumer[%s][%s/%s/%s/%s] find 
provider[%s/%s/%s/%s]",
-               request.ConsumerServiceId, service.ServiceInfo.Environment, 
service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, 
service.ServiceInfo.Version,
-               provider.Environment, provider.AppId, provider.ServiceName, 
provider.Version)
+       findFlag := func() string {
+               return fmt.Sprintf("Consumer[%s][%s/%s/%s/%s] find 
provider[%s/%s/%s/%s]",
+                       request.ConsumerServiceId, 
service.ServiceInfo.Environment, service.ServiceInfo.AppId, 
service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+                       provider.Environment, provider.AppId, 
provider.ServiceName, provider.Version)
+       }
        services, err := findServices(ctx, provider)
        if err != nil {
-               log.Error(fmt.Sprintf("find instance failed %s", findFlag), err)
+               log.Error(fmt.Sprintf("find instance failed %s", findFlag()), 
err)
                return &discovery.FindInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
        }
        if services == nil {
-               mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag)
+               mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag())
                log.Error("find instance failed", mes)
                return &discovery.FindInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -2015,7 +2023,7 @@ func (ds *DataSource) findInstance(ctx context.Context, 
request *discovery.FindI
        }
        instances, err := instancesFilter(ctx, serviceIDs)
        if err != nil {
-               log.Error(fmt.Sprintf("find instance failed %s", findFlag), err)
+               log.Error(fmt.Sprintf("find instance failed %s", findFlag()), 
err)
                return &discovery.FindInstancesResponse{
                        Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                }, err
@@ -2030,14 +2038,14 @@ func (ds *DataSource) findInstance(ctx context.Context, 
request *discovery.FindI
                if provider != nil {
                        err = AddServiceVersionRule(ctx, domainProject, 
service.ServiceInfo, provider)
                } else {
-                       mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag)
+                       mes := fmt.Errorf("%s failed, provider does not exist", 
findFlag())
                        log.Error("add service version rule failed", mes)
                        return &discovery.FindInstancesResponse{
                                Response: 
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
                        }, nil
                }
                if err != nil {
-                       log.Error(fmt.Sprintf("add service version rule failed 
%s", findFlag), err)
+                       log.Error(fmt.Sprintf("add service version rule failed 
%s", findFlag()), err)
                        return &discovery.FindInstancesResponse{
                                Response: 
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
                        }, err

Reply via email to