github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/managed_network.go (about) 1 package hedera 2 3 /*- 4 * 5 * Hedera Go SDK 6 * 7 * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ 22 23 import ( 24 "crypto/rand" 25 "math" 26 "math/big" 27 "sync" 28 "time" 29 ) 30 31 type _ManagedNetwork struct { 32 network map[string][]_IManagedNode 33 nodes []_IManagedNode 34 healthyNodes []_IManagedNode 35 healthyNodesMutex *sync.RWMutex 36 maxNodeAttempts int 37 minBackoff time.Duration 38 maxBackoff time.Duration 39 maxNodesPerTransaction *int 40 ledgerID *LedgerID 41 transportSecurity bool 42 verifyCertificate bool 43 minNodeReadmitPeriod time.Duration 44 maxNodeReadmitPeriod time.Duration 45 earliestReadmitTime time.Time 46 } 47 48 func _NewManagedNetwork() _ManagedNetwork { 49 return _ManagedNetwork{ 50 network: map[string][]_IManagedNode{}, 51 nodes: []_IManagedNode{}, 52 healthyNodes: []_IManagedNode{}, 53 healthyNodesMutex: &sync.RWMutex{}, 54 maxNodeAttempts: -1, 55 minBackoff: 8 * time.Second, 56 maxBackoff: 1 * time.Hour, 57 maxNodesPerTransaction: nil, 58 ledgerID: nil, 59 transportSecurity: false, 60 verifyCertificate: false, 61 minNodeReadmitPeriod: 8 * time.Second, 62 maxNodeReadmitPeriod: 1 * time.Hour, 63 } 64 } 65 66 func (this *_ManagedNetwork) _SetNetwork(network map[string]_IManagedNode) error { 67 newNodes := make([]_IManagedNode, len(this.nodes)) 68 newNodeKeys := map[string]bool{} 69 newNodeValues := map[string]bool{} 70 71 // Copy all the nodes into the `newNodes` list 72 copy(newNodes, this.nodes) 73 74 // Remove nodes from the old this which do not belong to the new this 75 for _, index := range _GetNodesToRemove(network, newNodes) { 76 node := newNodes[index] 77 78 if err := node._Close(); err != nil { 79 return err 80 } 81 82 if index == len(newNodes)-1 { 83 newNodes = newNodes[:index] 84 } else { 85 newNodes = append(newNodes[:index], newNodes[index+1:]...) 86 } 87 } 88 89 for _, node := range newNodes { 90 newNodeKeys[node._GetKey()] = true 91 newNodeValues[node._GetAddress()] = true 92 } 93 94 for key, value := range network { 95 _, keyOk := newNodeKeys[key] 96 _, valueOk := newNodeValues[value._GetAddress()] 97 98 if keyOk && valueOk { 99 continue 100 } 101 102 newNodes = append(newNodes, value) 103 } 104 105 newNetwork, newHealthyNodes := _CreateNetworkFromNodes(newNodes) 106 107 this.nodes = newNodes 108 this.network = newNetwork 109 this.healthyNodes = newHealthyNodes 110 111 return nil 112 } 113 114 func (this *_ManagedNetwork) _ReadmitNodes() { 115 now := time.Now() 116 117 this.healthyNodesMutex.Lock() 118 defer this.healthyNodesMutex.Unlock() 119 120 if this.earliestReadmitTime.Before(now) { 121 nextEarliestReadmitTime := now.Add(this.maxNodeReadmitPeriod) 122 123 for _, node := range this.nodes { 124 if node._GetReadmitTime() != nil && node._GetReadmitTime().After(now) && node._GetReadmitTime().Before(nextEarliestReadmitTime) { 125 nextEarliestReadmitTime = *node._GetReadmitTime() 126 } 127 } 128 129 this.earliestReadmitTime = nextEarliestReadmitTime 130 if this.earliestReadmitTime.Before(now.Add(this.minNodeReadmitPeriod)) { 131 this.earliestReadmitTime = now.Add(this.minNodeReadmitPeriod) 132 } 133 134 outer: 135 for _, node := range this.nodes { 136 for _, healthyNode := range this.healthyNodes { 137 if node == healthyNode { 138 continue outer 139 } 140 } 141 142 if node._GetReadmitTime().Before(now) { 143 this.healthyNodes = append(this.healthyNodes, node) 144 } 145 } 146 } 147 } 148 149 func (this *_ManagedNetwork) _GetNumberOfNodesForTransaction() int { // nolint 150 this._ReadmitNodes() 151 if this.maxNodesPerTransaction != nil { 152 return int(math.Min(float64(*this.maxNodesPerTransaction), float64(len(this.network)))) 153 } 154 155 return (len(this.network) + 3 - 1) / 3 156 } 157 158 func (this *_ManagedNetwork) _SetMaxNodesPerTransaction(max int) { 159 this.maxNodesPerTransaction = &max 160 } 161 162 func (this *_ManagedNetwork) _SetMaxNodeAttempts(max int) { 163 this.maxNodeAttempts = max 164 } 165 166 func (this *_ManagedNetwork) _GetMaxNodeAttempts() int { 167 return this.maxNodeAttempts 168 } 169 170 func (this *_ManagedNetwork) _SetMinNodeReadmitPeriod(min time.Duration) { 171 this.minNodeReadmitPeriod = min 172 this.earliestReadmitTime = time.Now().Add(this.minNodeReadmitPeriod) 173 } 174 175 func (this *_ManagedNetwork) _GetMinNodeReadmitPeriod() time.Duration { 176 return this.minNodeReadmitPeriod 177 } 178 179 func (this *_ManagedNetwork) _SetMaxNodeReadmitPeriod(max time.Duration) { 180 this.maxNodeReadmitPeriod = max 181 } 182 183 func (this *_ManagedNetwork) _GetMaxNodeReadmitPeriod() time.Duration { 184 return this.maxNodeReadmitPeriod 185 } 186 187 func (this *_ManagedNetwork) _SetMinBackoff(minBackoff time.Duration) { 188 this.minBackoff = minBackoff 189 for _, nod := range this.healthyNodes { 190 if nod != nil { 191 nod._SetMinBackoff(minBackoff) 192 } 193 } 194 } 195 196 func (this *_ManagedNetwork) _GetNode() _IManagedNode { 197 this._ReadmitNodes() 198 this.healthyNodesMutex.RLock() 199 defer this.healthyNodesMutex.RUnlock() 200 201 if len(this.healthyNodes) == 0 { 202 panic("failed to find a healthy working node") 203 } 204 205 bg := big.NewInt(int64(len(this.healthyNodes))) 206 index, _ := rand.Int(rand.Reader, bg) 207 return this.healthyNodes[index.Int64()] 208 } 209 210 func (this *_ManagedNetwork) _GetMinBackoff() time.Duration { 211 return this.minBackoff 212 } 213 214 func (this *_ManagedNetwork) _SetMaxBackoff(maxBackoff time.Duration) { 215 this.maxBackoff = maxBackoff 216 for _, node := range this.healthyNodes { 217 node._SetMaxBackoff(maxBackoff) 218 } 219 } 220 221 func (this *_ManagedNetwork) _GetMaxBackoff() time.Duration { 222 return this.maxBackoff 223 } 224 225 func (this *_ManagedNetwork) _GetLedgerID() *LedgerID { 226 return this.ledgerID 227 } 228 229 func (this *_ManagedNetwork) _SetLedgerID(id LedgerID) *_ManagedNetwork { 230 this.ledgerID = &id 231 return this 232 } 233 234 func (this *_ManagedNetwork) _Close() error { 235 for _, conn := range this.healthyNodes { 236 if err := conn._Close(); err != nil { 237 return err 238 } 239 } 240 241 return nil 242 } 243 244 func _CreateNetworkFromNodes(nodes []_IManagedNode) (network map[string][]_IManagedNode, healthyNodes []_IManagedNode) { 245 healthyNodes = []_IManagedNode{} 246 network = map[string][]_IManagedNode{} 247 248 for _, node := range nodes { 249 if node._IsHealthy() { 250 healthyNodes = append(healthyNodes, node) 251 } 252 253 value, ok := network[node._GetKey()] 254 if !ok { 255 value = []_IManagedNode{} 256 } 257 value = append(value, node) 258 network[node._GetKey()] = value 259 } 260 261 return network, healthyNodes 262 } 263 264 func (this *_ManagedNetwork) _SetTransportSecurity(transportSecurity bool) (err error) { 265 if this.transportSecurity != transportSecurity { 266 if err := this._Close(); err != nil { 267 return err 268 } 269 270 newNodes := make([]_IManagedNode, len(this.nodes)) 271 272 copy(newNodes, this.nodes) 273 274 for i, node := range newNodes { 275 if transportSecurity { 276 newNodes[i] = node._ToSecure() 277 } else { 278 newNodes[i] = node._ToInsecure() 279 } 280 } 281 282 newNetwork, newHealthyNodes := _CreateNetworkFromNodes(newNodes) 283 284 this.nodes = newNodes 285 this.healthyNodes = newHealthyNodes 286 this.network = newNetwork 287 } 288 289 this.transportSecurity = transportSecurity 290 return nil 291 } 292 293 func _GetNodesToRemove(network map[string]_IManagedNode, nodes []_IManagedNode) []int { 294 nodeIndices := []int{} 295 296 for i := len(nodes) - 1; i >= 0; i-- { 297 if _, ok := network[nodes[i]._GetKey()]; !ok { 298 nodeIndices = append(nodeIndices, i) 299 } 300 } 301 302 return nodeIndices 303 } 304 305 func (this *_ManagedNetwork) _SetVerifyCertificate(verify bool) *_ManagedNetwork { 306 for _, node := range this.nodes { 307 node._SetVerifyCertificate(verify) 308 } 309 310 this.verifyCertificate = verify 311 return this 312 } 313 314 func (this *_ManagedNetwork) _GetVerifyCertificate() bool { 315 return this.verifyCertificate 316 }