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 }