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  }