moonstream/nodes/node_balancer/cmd/nodebalancer/clients.go

129 wiersze
3.0 KiB
Go

package main
import (
"errors"
"reflect"
"sync"
"time"
)
var (
ethereumClientPool ClientPool
polygonClientPool ClientPool
xdaiClientPool ClientPool
)
// Structure to define user access according with Brood resources
type ClientResourceData struct {
UserID string `json:"user_id"`
AccessID string `json:"access_id"`
Name string `json:"name"`
Description string `json:"description"`
BlockchainAccess bool `json:"blockchain_access"`
ExtendedMethods bool `json:"extended_methods"`
LastAccessTs int64 `json:"last_access_ts"`
dataSource string
}
// Node - which one node client worked with
// LastCallTs - timestamp from last call
type Client struct {
Node *Node
LastCallTs int64
mux sync.RWMutex
}
// Where id is a key and equal to ClientResourceData -> AccessID
type ClientPool struct {
Client map[string]*Client
}
// Generate pools for clients for different blockchains
func CreateClientPools() {
ethereumClientPool.Client = make(map[string]*Client)
polygonClientPool.Client = make(map[string]*Client)
xdaiClientPool.Client = make(map[string]*Client)
}
// Return client pool corresponding to provided blockchain
func GetClientPool(blockchain string) (*ClientPool, error) {
var cpool *ClientPool
if blockchain == "ethereum" {
cpool = &ethereumClientPool
} else if blockchain == "polygon" {
cpool = &polygonClientPool
} else if blockchain == "xdai" {
cpool = &xdaiClientPool
} else {
return nil, errors.New("Unsupported blockchain provided")
}
return cpool, nil
}
// Updates client last appeal to node
func (client *Client) UpdateClientLastCall() {
ts := time.Now().Unix()
client.mux.Lock()
client.LastCallTs = ts
client.mux.Unlock()
}
// Get number of seconds from current last call to client node
func (client *Client) GetClientLastCallDiff() (lastCallTs int64) {
ts := time.Now().Unix()
client.mux.RLock()
lastCallTs = ts - client.LastCallTs
client.mux.RUnlock()
return lastCallTs
}
// Find clint with same ID and update timestamp or
// add new one if doesn't exist
func (cpool *ClientPool) AddClientNode(id string, node *Node) {
if cpool.Client[id] != nil {
if reflect.DeepEqual(cpool.Client[id].Node, node) {
cpool.Client[id].UpdateClientLastCall()
return
}
}
cpool.Client[id] = &Client{
Node: node,
LastCallTs: time.Now().Unix(),
}
}
// Get client hot node if exists
func (cpool *ClientPool) GetClientNode(id string) *Node {
if cpool.Client[id] != nil {
lastCallTs := cpool.Client[id].GetClientLastCallDiff()
if lastCallTs < NB_CLIENT_NODE_KEEP_ALIVE {
cpool.Client[id].UpdateClientLastCall()
return cpool.Client[id].Node
}
delete(cpool.Client, id)
}
return nil
}
// Clean client list of hot outdated nodes
func (cpool *ClientPool) CleanInactiveClientNodes() int {
cnt := 0
for id, client := range cpool.Client {
lastCallTs := client.GetClientLastCallDiff()
if lastCallTs >= NB_CLIENT_NODE_KEEP_ALIVE {
delete(cpool.Client, id)
} else {
cnt += 1
}
}
return cnt
}