in datasource/mongo/ms.go [263:349]
func (ds *MetadataManager) UnregisterService(ctx context.Context, request *discovery.DeleteServiceRequest) error {
remoteIP := util.GetIPFromContext(ctx)
serviceID := request.ServiceId
force := request.Force
title := "delete"
if force {
title = "force delete"
}
if serviceID == apt.Service.ServiceId {
log.Error(fmt.Sprintf("%s micro-service %s failed, operator: %s", title, serviceID, remoteIP), mutil.ErrNotAllowDeleteSC)
return discovery.NewError(discovery.ErrInvalidParams, mutil.ErrNotAllowDeleteSC.Error())
}
microservice, err := GetServiceByID(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",
title, serviceID, remoteIP))
return discovery.NewError(discovery.ErrServiceNotExists, "Service does not exist.")
}
log.Error(fmt.Sprintf("%s micro-service %s failed, get service file failed, operator: %s",
title, serviceID, remoteIP), err)
return discovery.NewError(discovery.ErrInternal, err.Error())
}
// 强制删除,则与该服务相关的信息删除,非强制删除: 如果作为该被依赖(作为provider,提供服务,且不是只存在自依赖)或者存在实例,则不能删除
if !force {
dr := NewProviderDependencyRelation(ctx, util.ParseDomainProject(ctx), microservice.Service)
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.NewError(discovery.ErrInternal, err.Error())
}
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.NewError(discovery.ErrDependedOnConsumer, "Can not delete this service, other service rely it.")
}
//todo wait for dep interface
num, err := dmongo.GetClient().GetDB().Collection(model.CollectionInstance).CountDocuments(ctx, bson.M{mutil.ConnectWithDot([]string{model.ColumnInstance, model.ColumnServiceID}): serviceID})
if err != nil {
log.Error(fmt.Sprintf("delete micro-service[%s] failed, get instances number failed, operator: %s",
serviceID, remoteIP), err)
return discovery.NewError(discovery.ErrUnavailableBackend, err.Error())
}
if num != 0 {
log.Error(fmt.Sprintf("delete micro-service[%s] failed, service deployed instances, operator: %s",
serviceID, remoteIP), nil)
return discovery.NewError(discovery.ErrDeployedInstance, "Can not delete the service deployed instance(s).")
}
}
_, err = dmongo.GetClient().GetDB().Collection(model.CollectionSchema).BulkWrite(ctx,
[]mongo.WriteModel{mongo.NewDeleteManyModel().SetFilter(bson.M{model.ColumnServiceID: serviceID})})
if err != nil {
log.Error(fmt.Sprintf("micro-service[%s] failed, operator: %s", serviceID, remoteIP), err)
return discovery.NewError(discovery.ErrUnavailableBackend, err.Error())
}
_, err = dmongo.GetClient().GetDB().Collection(model.CollectionInstance).BulkWrite(ctx,
[]mongo.WriteModel{mongo.NewDeleteManyModel().SetFilter(bson.M{mutil.ConnectWithDot([]string{model.ColumnInstance, model.ColumnServiceID}): serviceID})})
if err != nil {
log.Error(fmt.Sprintf("micro-service[%s] failed, operator: %s", serviceID, remoteIP), err)
return discovery.NewError(discovery.ErrUnavailableBackend, err.Error())
}
err = deleteServiceTxn(ctx, err, serviceID, force)
if err != nil {
log.Error(fmt.Sprintf("micro-service[%s] failed, operator: %s", serviceID, remoteIP), err)
return discovery.NewError(discovery.ErrUnavailableBackend, err.Error())
}
domainProject := util.ToDomainProject(microservice.Domain, microservice.Project)
serviceKey := &discovery.MicroServiceKey{
Tenant: domainProject,
Environment: microservice.Service.Environment,
AppId: microservice.Service.AppId,
ServiceName: microservice.Service.ServiceName,
Version: microservice.Service.Version,
Alias: microservice.Service.Alias,
}
err = DeleteDependencyForDeleteService(domainProject, serviceID, serviceKey)
if err != nil {
log.Error(fmt.Sprintf("micro-service[%s] failed, operator: %s", serviceID, remoteIP), err)
return discovery.NewError(discovery.ErrUnavailableBackend, err.Error())
}
return nil
}