github.com/polarismesh/polaris@v1.17.8/store/boltdb/admin.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 "fmt" 22 "sync" 23 "time" 24 25 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 26 27 "github.com/polarismesh/polaris/common/eventhub" 28 "github.com/polarismesh/polaris/common/model" 29 "github.com/polarismesh/polaris/common/utils" 30 "github.com/polarismesh/polaris/store" 31 ) 32 33 type adminStore struct { 34 handler BoltHandler 35 leMap map[string]bool 36 mutex sync.Mutex 37 } 38 39 // StartLeaderElection 40 func (m *adminStore) StartLeaderElection(key string) error { 41 m.mutex.Lock() 42 defer m.mutex.Unlock() 43 44 _, ok := m.leMap[key] 45 if ok { 46 return nil 47 } 48 m.leMap[key] = true 49 _ = eventhub.Publish(eventhub.LeaderChangeEventTopic, store.LeaderChangeEvent{Key: key, Leader: true}) 50 return nil 51 } 52 53 // IsLeader 54 func (m *adminStore) IsLeader(key string) bool { 55 m.mutex.Lock() 56 defer m.mutex.Unlock() 57 58 v, ok := m.leMap[key] 59 if ok { 60 return v 61 } 62 return false 63 } 64 65 // ListLeaderElections 66 func (m *adminStore) ListLeaderElections() ([]*model.LeaderElection, error) { 67 m.mutex.Lock() 68 defer m.mutex.Unlock() 69 70 var out []*model.LeaderElection 71 for k, v := range m.leMap { 72 item := &model.LeaderElection{ 73 ElectKey: k, 74 Host: utils.LocalHost, 75 Ctime: 0, 76 Mtime: time.Now().Unix(), 77 Valid: v, 78 } 79 item.CreateTime = time.Unix(item.Ctime, 0) 80 item.ModifyTime = time.Unix(item.Mtime, 0) 81 82 out = append(out, item) 83 } 84 return out, nil 85 } 86 87 // ReleaseLeaderElection 88 func (m *adminStore) ReleaseLeaderElection(key string) error { 89 m.mutex.Lock() 90 defer m.mutex.Unlock() 91 v, ok := m.leMap[key] 92 if !ok { 93 return fmt.Errorf("LeaderElection(%s) not started", key) 94 } 95 96 if v { 97 m.leMap[key] = false 98 _ = eventhub.Publish(eventhub.LeaderChangeEventTopic, store.LeaderChangeEvent{Key: key, Leader: false}) 99 } 100 101 return nil 102 } 103 104 // BatchCleanDeletedInstances 105 func (m *adminStore) BatchCleanDeletedInstances(timeout time.Duration, batchSize uint32) (uint32, error) { 106 mtime := time.Now().Add(-timeout) 107 fields := []string{insFieldValid, insFieldModifyTime} 108 values, err := m.handler.LoadValuesByFilter(tblNameInstance, fields, &model.Instance{}, 109 func(m map[string]interface{}) bool { 110 valid, ok := m[insFieldValid] 111 if !ok { 112 return false 113 } 114 if valid.(bool) { 115 return false 116 } 117 118 modifyTime, ok := m[insFieldModifyTime] 119 if !ok { 120 return false 121 } 122 if modifyTime.(time.Time).After(mtime) { 123 return false 124 } 125 126 return true 127 }) 128 if err != nil { 129 return 0, err 130 } 131 if len(values) == 0 { 132 return 0, nil 133 } 134 135 var count uint32 = 0 136 keys := make([]string, 0, batchSize) 137 for k := range values { 138 keys = append(keys, k) 139 count++ 140 if count >= batchSize { 141 break 142 } 143 } 144 err = m.handler.DeleteValues(tblNameInstance, keys) 145 if err != nil { 146 return count, err 147 } 148 return count, nil 149 } 150 151 func (m *adminStore) GetUnHealthyInstances(timeout time.Duration, limit uint32) ([]string, error) { 152 return m.getUnHealthyInstancesBefore(time.Now().Add(-timeout), limit) 153 } 154 155 func (m *adminStore) getUnHealthyInstancesBefore(mtime time.Time, limit uint32) ([]string, error) { 156 fields := []string{insFieldProto, insFieldValid} 157 instances, err := m.handler.LoadValuesByFilter(tblNameInstance, fields, &model.Instance{}, 158 func(m map[string]interface{}) bool { 159 160 valid, ok := m[insFieldValid] 161 if ok && !valid.(bool) { 162 return false 163 } 164 165 insProto, ok := m[insFieldProto] 166 if !ok { 167 return false 168 } 169 170 ins := insProto.(*apiservice.Instance) 171 172 insMtime, err := time.Parse("2006-01-02 15:04:05", ins.GetMtime().GetValue()) 173 if err != nil { 174 log.Errorf("[Store][boltdb] parse instance mtime error, %v", err) 175 return false 176 } 177 178 if insMtime.Before(mtime) { 179 return false 180 } 181 182 if !ins.GetEnableHealthCheck().GetValue() { 183 return false 184 } 185 186 if ins.GetHealthy().GetValue() { 187 return false 188 } 189 190 return true 191 }) 192 193 if err != nil { 194 log.Errorf("[Store][boltdb] load instance from kv error, %v", err) 195 return nil, err 196 } 197 198 var instanceIds []string 199 var count uint32 = 0 200 for _, v := range instances { 201 instanceIds = append(instanceIds, v.(*model.Instance).ID()) 202 count += 1 203 if count >= limit { 204 break 205 } 206 } 207 208 return instanceIds, nil 209 } 210 211 // BatchCleanDeletedClients 212 func (m *adminStore) BatchCleanDeletedClients(timeout time.Duration, batchSize uint32) (uint32, error) { 213 mtime := time.Now().Add(-timeout) 214 fields := []string{ClientFieldValid, ClientFieldMtime} 215 values, err := m.handler.LoadValuesByFilter(tblClient, fields, &model.Client{}, 216 func(m map[string]interface{}) bool { 217 valid, ok := m[ClientFieldValid] 218 if !ok { 219 return false 220 } 221 if valid.(bool) { 222 return false 223 } 224 225 modifyTime, ok := m[ClientFieldMtime] 226 if !ok { 227 return false 228 } 229 if modifyTime.(time.Time).After(mtime) { 230 return false 231 } 232 233 return true 234 }) 235 if err != nil { 236 return 0, err 237 } 238 if len(values) == 0 { 239 return 0, nil 240 } 241 242 var count uint32 = 0 243 keys := make([]string, 0, batchSize) 244 for k := range values { 245 keys = append(keys, k) 246 count++ 247 if count >= batchSize { 248 break 249 } 250 } 251 err = m.handler.DeleteValues(tblClient, keys) 252 if err != nil { 253 return count, err 254 } 255 return count, nil 256 }