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 {