github.com/polarismesh/polaris@v1.17.8/service/batch/future.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package batch
    19  
    20  import (
    21  	"time"
    22  
    23  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    24  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    25  	"go.uber.org/zap"
    26  
    27  	"github.com/polarismesh/polaris/common/metrics"
    28  	"github.com/polarismesh/polaris/common/model"
    29  	"github.com/polarismesh/polaris/plugin"
    30  )
    31  
    32  // InstanceFuture 创建实例的异步结构体
    33  type InstanceFuture struct {
    34  	// 任务开始时间
    35  	begin time.Time
    36  	// 服务的id
    37  	serviceId string
    38  	// api请求对象
    39  	request *apiservice.Instance
    40  	// 从数据库中读取到的model信息
    41  	instance *model.Instance
    42  	// 记录对外API的错误码
    43  	code apimodel.Code
    44  	// 这个 future 是否会被外部调用 Wait 接口
    45  	needWait bool
    46  	// 执行成功/失败的应答chan
    47  	result chan error
    48  	// 健康与否
    49  	healthy bool
    50  	// lastHeartbeatTimeSec 实例最后一次心跳上报时间
    51  	lastHeartbeatTimeSec int64
    52  }
    53  
    54  // Reply future的应答
    55  func (future *InstanceFuture) Reply(cur time.Time, code apimodel.Code, result error) {
    56  	reportRegisInstanceCost(future.begin, cur, code)
    57  	if code == apimodel.Code_InstanceRegisTimeout {
    58  		metrics.ReportDropInstanceRegisTask()
    59  	}
    60  
    61  	if !future.needWait {
    62  		if result != nil {
    63  			log.Error("[Instance][Regis] receive future result", zap.String("service-id", future.serviceId),
    64  				zap.Error(result))
    65  		}
    66  		return
    67  	}
    68  
    69  	future.code = code
    70  	select {
    71  	case future.result <- result:
    72  	default:
    73  		log.Warnf("[Batch] instance(%s) future is not captured", future.request.GetId().GetValue())
    74  	}
    75  }
    76  
    77  // Wait 外部调用者,需要调用Wait等待执行结果
    78  func (future *InstanceFuture) Wait() error {
    79  	if !future.needWait {
    80  		return nil
    81  	}
    82  	return <-future.result
    83  }
    84  
    85  // SetInstance 设置ins
    86  func (future *InstanceFuture) SetInstance(instance *model.Instance) {
    87  	future.instance = instance
    88  }
    89  
    90  // Instance 获取ins
    91  func (future *InstanceFuture) Instance() *model.Instance {
    92  	return future.instance
    93  }
    94  
    95  // CanDrop 该 future 是否可以丢弃
    96  func (future *InstanceFuture) CanDrop() bool {
    97  	return !future.needWait
    98  }
    99  
   100  // Code 获取code
   101  func (future *InstanceFuture) Code() apimodel.Code {
   102  	return future.code
   103  }
   104  
   105  // sendReply 批量答复futures
   106  func sendReply(futures interface{}, code apimodel.Code, result error) {
   107  	cur := time.Now()
   108  	switch futureType := futures.(type) {
   109  	case []*InstanceFuture:
   110  		for _, entry := range futureType {
   111  			entry.Reply(cur, code, result)
   112  		}
   113  	case map[string]*InstanceFuture:
   114  		for _, entry := range futureType {
   115  			entry.Reply(cur, code, result)
   116  		}
   117  	default:
   118  		log.Errorf("[Controller] not found reply futures type: %T", futures)
   119  	}
   120  }
   121  
   122  func reportRegisInstanceCost(begin, cur time.Time, code apimodel.Code) {
   123  	diff := cur.Sub(begin)
   124  	plugin.GetStatis().ReportCallMetrics(metrics.CallMetric{
   125  		Type:     metrics.SystemCallMetric,
   126  		API:      "AsyncRegisInstance",
   127  		Code:     int(code),
   128  		Duration: diff,
   129  	})
   130  	metrics.ReportInstanceRegisCost(diff)
   131  }