github.com/cryptogateway/go-paymex@v0.0.0-20210204174735-96277fb1e602/les/lespay/client/api.go (about) 1 // Copyright 2020 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package client 18 19 import ( 20 "time" 21 22 "github.com/cryptogateway/go-paymex/common/mclock" 23 "github.com/cryptogateway/go-paymex/les/utils" 24 "github.com/cryptogateway/go-paymex/p2p/enode" 25 ) 26 27 // PrivateClientAPI implements the lespay client side API 28 type PrivateClientAPI struct { 29 vt *ValueTracker 30 } 31 32 // NewPrivateClientAPI creates a PrivateClientAPI 33 func NewPrivateClientAPI(vt *ValueTracker) *PrivateClientAPI { 34 return &PrivateClientAPI{vt} 35 } 36 37 // parseNodeStr converts either an enode address or a plain hex node id to enode.ID 38 func parseNodeStr(nodeStr string) (enode.ID, error) { 39 if id, err := enode.ParseID(nodeStr); err == nil { 40 return id, nil 41 } 42 if node, err := enode.Parse(enode.ValidSchemes, nodeStr); err == nil { 43 return node.ID(), nil 44 } else { 45 return enode.ID{}, err 46 } 47 } 48 49 // RequestStats returns the current contents of the reference request basket, with 50 // request values meaning average per request rather than total. 51 func (api *PrivateClientAPI) RequestStats() []RequestStatsItem { 52 return api.vt.RequestStats() 53 } 54 55 // Distribution returns a distribution as a series of (X, Y) chart coordinates, 56 // where the X axis is the response time in seconds while the Y axis is the amount of 57 // service value received with a response time close to the X coordinate. 58 // The distribution is optionally normalized to a sum of 1. 59 // If nodeStr == "" then the global distribution is returned, otherwise the individual 60 // distribution of the specified server node. 61 func (api *PrivateClientAPI) Distribution(nodeStr string, normalized bool) (RtDistribution, error) { 62 var expFactor utils.ExpirationFactor 63 if !normalized { 64 expFactor = utils.ExpFactor(api.vt.StatsExpirer().LogOffset(mclock.Now())) 65 } 66 if nodeStr == "" { 67 return api.vt.RtStats().Distribution(normalized, expFactor), nil 68 } 69 if id, err := parseNodeStr(nodeStr); err == nil { 70 return api.vt.GetNode(id).RtStats().Distribution(normalized, expFactor), nil 71 } else { 72 return RtDistribution{}, err 73 } 74 } 75 76 // Timeout suggests a timeout value based on either the global distribution or the 77 // distribution of the specified node. The parameter is the desired rate of timeouts 78 // assuming a similar distribution in the future. 79 // Note that the actual timeout should have a sensible minimum bound so that operating 80 // under ideal working conditions for a long time (for example, using a local server 81 // with very low response times) will not make it very hard for the system to accommodate 82 // longer response times in the future. 83 func (api *PrivateClientAPI) Timeout(nodeStr string, failRate float64) (float64, error) { 84 if nodeStr == "" { 85 return float64(api.vt.RtStats().Timeout(failRate)) / float64(time.Second), nil 86 } 87 if id, err := parseNodeStr(nodeStr); err == nil { 88 return float64(api.vt.GetNode(id).RtStats().Timeout(failRate)) / float64(time.Second), nil 89 } else { 90 return 0, err 91 } 92 } 93 94 // Value calculates the total service value provided either globally or by the specified 95 // server node, using a weight function based on the given timeout. 96 func (api *PrivateClientAPI) Value(nodeStr string, timeout float64) (float64, error) { 97 wt := TimeoutWeights(time.Duration(timeout * float64(time.Second))) 98 expFactor := utils.ExpFactor(api.vt.StatsExpirer().LogOffset(mclock.Now())) 99 if nodeStr == "" { 100 return api.vt.RtStats().Value(wt, expFactor), nil 101 } 102 if id, err := parseNodeStr(nodeStr); err == nil { 103 return api.vt.GetNode(id).RtStats().Value(wt, expFactor), nil 104 } else { 105 return 0, err 106 } 107 }