github.com/polarismesh/polaris@v1.17.8/store/boltdb/client.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 boltdb 19 20 import ( 21 "encoding/json" 22 "time" 23 24 apimodel "github.com/polarismesh/specification/source/go/api/v1/model" 25 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 26 bolt "go.etcd.io/bbolt" 27 "go.uber.org/zap" 28 29 "github.com/polarismesh/polaris/common/model" 30 commontime "github.com/polarismesh/polaris/common/time" 31 "github.com/polarismesh/polaris/common/utils" 32 ) 33 34 const ( 35 tblClient string = "client" 36 37 ClientFieldHost string = "Host" 38 ClientFieldType string = "Type" 39 ClientFieldVersion string = "Version" 40 ClientFieldLocation string = "Location" 41 ClientFieldId string = "Id" 42 ClientFieldStatArrStr string = "StatArrStr" 43 ClientFieldCtime string = "Ctime" 44 ClientFieldMtime string = "Mtime" 45 ClientFieldValid string = "Valid" 46 ) 47 48 type clientObject struct { 49 Host string 50 Type string 51 Version string 52 Location map[string]string 53 Id string 54 Ctime time.Time 55 Mtime time.Time 56 StatArrStr string 57 Valid bool 58 } 59 60 type clientStore struct { 61 handler BoltHandler 62 } 63 64 // BatchAddClients insert the client info 65 func (cs *clientStore) BatchAddClients(clients []*model.Client) error { 66 if err := cs.handler.Execute(true, func(tx *bolt.Tx) error { 67 for i := range clients { 68 client := clients[i] 69 saveVal, err := convertToClientObject(client) 70 if err != nil { 71 return err 72 } 73 74 if err := saveValue(tx, tblClient, saveVal.Id, saveVal); err != nil { 75 return err 76 } 77 } 78 return nil 79 }); err != nil { 80 log.Error("[Client] batch add clients", zap.Error(err)) 81 return err 82 } 83 84 return nil 85 } 86 87 // BatchDeleteClients delete the client info 88 func (cs *clientStore) BatchDeleteClients(ids []string) error { 89 err := cs.handler.Execute(true, func(tx *bolt.Tx) error { 90 for i := range ids { 91 properties := make(map[string]interface{}) 92 properties[ClientFieldValid] = false 93 properties[ClientFieldMtime] = time.Now() 94 95 if err := updateValue(tx, tblClient, ids[i], properties); err != nil { 96 log.Error("[Client] batch delete clients", zap.Error(err)) 97 return err 98 } 99 } 100 101 return nil 102 }) 103 104 return err 105 } 106 107 // GetMoreClients 根据mtime获取增量clients,返回所有store的变更信息 108 func (cs *clientStore) GetMoreClients(mtime time.Time, firstUpdate bool) (map[string]*model.Client, error) { 109 fields := []string{ClientFieldMtime} 110 ret, err := cs.handler.LoadValuesByFilter(tblClient, fields, &clientObject{}, func(m map[string]interface{}) bool { 111 if firstUpdate { 112 return true 113 } 114 return m[ClientFieldMtime].(time.Time).After(mtime) 115 }) 116 117 if err != nil { 118 log.Error("[Client] get more clients for cache", zap.Error(err)) 119 return nil, err 120 } 121 122 clients := make(map[string]*model.Client, len(ret)) 123 for k, v := range ret { 124 client, err := convertToModelClient(v.(*clientObject)) 125 if err != nil { 126 log.Error("[Client] convert clientObject to model.Client", zap.Error(err)) 127 return nil, err 128 } 129 130 clients[k] = client 131 } 132 133 return clients, nil 134 } 135 136 func convertToClientObject(client *model.Client) (*clientObject, error) { 137 stat := client.Proto().Stat 138 data, err := json.Marshal(stat) 139 if err != nil { 140 return nil, err 141 } 142 tn := time.Now() 143 return &clientObject{ 144 Host: client.Proto().GetHost().GetValue(), 145 Type: client.Proto().GetType().String(), 146 Version: client.Proto().GetVersion().GetValue(), 147 Location: map[string]string{ 148 "region": client.Proto().GetLocation().GetRegion().GetValue(), 149 "zone": client.Proto().GetLocation().GetZone().GetValue(), 150 "campus": client.Proto().GetLocation().GetCampus().GetValue(), 151 }, 152 Id: client.Proto().GetId().GetValue(), 153 Ctime: tn, 154 Mtime: tn, 155 StatArrStr: string(data), 156 Valid: true, 157 }, nil 158 } 159 160 func convertToModelClient(client *clientObject) (*model.Client, error) { 161 stat := make([]*apiservice.StatInfo, 0, 4) 162 err := json.Unmarshal([]byte(client.StatArrStr), &stat) 163 if err != nil { 164 return nil, err 165 } 166 167 c := &apiservice.Client{ 168 Id: utils.NewStringValue(client.Id), 169 Host: utils.NewStringValue(client.Host), 170 Type: apiservice.Client_ClientType(apiservice.Client_ClientType_value[client.Type]), 171 Version: utils.NewStringValue(client.Version), 172 Ctime: utils.NewStringValue(commontime.Time2String(client.Ctime)), 173 Mtime: utils.NewStringValue(commontime.Time2String(client.Mtime)), 174 Location: &apimodel.Location{ 175 Region: utils.NewStringValue(client.Location["region"]), 176 Zone: utils.NewStringValue(client.Location["zone"]), 177 Campus: utils.NewStringValue(client.Location["campus"]), 178 }, 179 Stat: stat, 180 } 181 182 mc := model.NewClient(c) 183 mc.SetValid(client.Valid) 184 return mc, nil 185 }