blob: 8c2daff6166f5f659978424c1b569314d6b18859 [file] [log] [blame]
package task
import (
"context"
"errors"
"strconv"
"strings"
"time"
"github.com/apache/servicecomb-service-center/pkg/log"
"github.com/apache/servicecomb-service-center/pkg/util"
apt "github.com/apache/servicecomb-service-center/server/core"
pb "github.com/apache/servicecomb-service-center/server/core/proto"
serviceUtil "github.com/apache/servicecomb-service-center/server/service/util"
)
// ClearNoInstanceService clears services which have no instance
func ClearNoInstanceServices(serviceTTL time.Duration) error {
services, err := serviceUtil.GetAllServicesAcrossDomainProject(context.Background())
if err != nil {
return err
}
if len(services) == 0 {
log.Info("no service found, no need to clear")
return nil
}
timeLimit := time.Now().Add(0 - serviceTTL)
log.Infof("clear no-instance services created before %s", timeLimit)
timeLimitStamp := strconv.FormatInt(timeLimit.Unix(), 10)
for domainProject, svcList := range services {
if len(svcList) == 0 {
continue
}
ctx, err := ctxFromDomainProject(domainProject)
if err != nil {
log.Errorf(err, "get domain project context failed")
continue
}
for _, svc := range svcList {
if svc == nil {
continue
}
ok, err := shouldClear(ctx, timeLimitStamp, svc)
if err != nil {
log.Errorf(err, "check service clear necessity failed")
continue
}
if !ok {
continue
}
//delete this service
svcCtxStr := "domainProject: " + domainProject + ", " +
"env: " + svc.Environment + ", " +
"service: " + util.StringJoin([]string{svc.AppId, svc.ServiceName, svc.Version}, apt.SPLIT)
delSvcReq := &pb.DeleteServiceRequest{
ServiceId: svc.ServiceId,
Force: true, //force delete
}
delSvcResp, err := apt.ServiceAPI.Delete(ctx, delSvcReq)
if err != nil {
log.Errorf(err, "clear service failed, %s", svcCtxStr)
continue
}
if delSvcResp.Response.GetCode() != pb.Response_SUCCESS {
log.Errorf(nil, "clear service failed, %s, %s", delSvcResp.Response.GetMessage(), svcCtxStr)
continue
}
log.Warnf("clear service success, %s", svcCtxStr)
}
}
return nil
}
func ctxFromDomainProject(domainProject string) (ctx context.Context, err error) {
splitIndex := strings.Index(domainProject, apt.SPLIT)
if splitIndex == -1 {
return nil, errors.New("invalid domainProject: " + domainProject)
}
domain := domainProject[:splitIndex]
project := domainProject[splitIndex+1:]
return util.SetDomainProject(context.Background(), domain, project), nil
}
//check whether a service should be cleared
func shouldClear(ctx context.Context, timeLimitStamp string, svc *pb.MicroService) (bool, error) {
//ignore a service if it is created after timeLimitStamp
if svc.Timestamp > timeLimitStamp {
return false, nil
}
getInstsReq := &pb.GetInstancesRequest{
ConsumerServiceId: svc.ServiceId,
ProviderServiceId: svc.ServiceId,
}
getInstsResp, err := apt.InstanceAPI.GetInstances(ctx, getInstsReq)
if err != nil {
return false, err
}
if getInstsResp.Response.GetCode() != pb.Response_SUCCESS {
return false, errors.New("get instance failed: " + getInstsResp.Response.GetMessage())
}
//ignore a service if it has instances
if len(getInstsResp.Instances) > 0 {
return false, nil
}
return true, nil
}