diff --git a/rpc/rpc.go b/rpc/rpc.go index 34dbddd..338fdf0 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -28,6 +28,7 @@ type RPCClient struct { Name string sick bool client *http.Client + info atomic.Value } type GetBlockTemplateReply struct { @@ -38,6 +39,14 @@ type GetBlockTemplateReply struct { PrevHash string `json:"prev_hash"` } +type GetInfoReply struct { + IncomingConnections int64 `json:"incoming_connections_count"` + OutgoingConnections int64 `json:"outgoing_connections_count"` + Status string `json:"status"` + Height int64 `json:"height"` + TxPoolSize int64 `json:"tx_pool_size"` +} + type JSONRpcResp struct { Id *json.RawMessage `json:"id"` Result *json.RawMessage `json:"result"` @@ -71,6 +80,19 @@ func (r *RPCClient) GetBlockTemplate(reserveSize int, address string) (*GetBlock return reply, err } +func (r *RPCClient) GetInfo() (*GetInfoReply, error) { + params := make(map[string]interface{}) + rpcResp, err := r.doPost(r.Url.String(), "get_info", params) + var reply *GetInfoReply + if err != nil { + return nil, err + } + if rpcResp.Result != nil { + err = json.Unmarshal(*rpcResp.Result, &reply) + } + return reply, err +} + func (r *RPCClient) SubmitBlock(hash string) (*JSONRpcResp, error) { return r.doPost(r.Url.String(), "submitblock", []string{hash}) } @@ -145,3 +167,16 @@ func (r *RPCClient) markAlive() { } r.Unlock() } + +func (r *RPCClient) UpdateInfo() (*GetInfoReply, error) { + info, err := r.GetInfo() + if err == nil { + r.info.Store(info) + } + return info, err +} + +func (r *RPCClient) Info() *GetInfoReply { + reply, _ := r.info.Load().(*GetInfoReply) + return reply +} diff --git a/stratum/api.go b/stratum/api.go index 13e395c..08806c8 100644 --- a/stratum/api.go +++ b/stratum/api.go @@ -58,6 +58,7 @@ func convertUpstream(u *rpc.RPCClient) map[string]interface{} { "rejects": atomic.LoadInt64(&u.Rejects), "lastSubmissionAt": atomic.LoadInt64(&u.LastSubmissionAt), "failsCount": atomic.LoadInt64(&u.FailsCount), + "info": u.Info(), } return upstream } diff --git a/stratum/stratum.go b/stratum/stratum.go index b4958e9..7cef82a 100644 --- a/stratum/stratum.go +++ b/stratum/stratum.go @@ -100,6 +100,9 @@ func NewStratum(cfg *pool.Config) *StratumServer { checkIntv, _ := time.ParseDuration(cfg.UpstreamCheckInterval) checkTimer := time.NewTimer(checkIntv) + infoIntv, _ := time.ParseDuration(cfg.UpstreamCheckInterval) + infoTimer := time.NewTimer(infoIntv) + // Init block template go stratum.refreshBlockTemplate(false) @@ -123,6 +126,32 @@ func NewStratum(cfg *pool.Config) *StratumServer { } }() + go func() { + for { + select { + case <-infoTimer.C: + poll := func(v *rpc.RPCClient) { + _, err := v.UpdateInfo() + if err != nil { + log.Printf("Unable to update info on upstream %s: %v", v.Name, err) + } + } + current := stratum.rpc() + poll(current) + + // Async rpc call to not block on rpc timeout, ignoring current + go func() { + for _, v := range stratum.upstreams { + if v != current { + poll(v) + } + } + }() + infoTimer.Reset(infoIntv) + } + } + }() + return stratum } diff --git a/www/index.html b/www/index.html index b583b17..2e6c078 100644 --- a/www/index.html +++ b/www/index.html @@ -70,7 +70,7 @@

Upstream

- +
@@ -89,11 +89,21 @@ {{else}} {{/if}} - - - - - + + + + + {{#if info}} + + + + {{/if}} {{/each}}
Name Url{{name}}{{url}}{{formatNumber accepts}}{{formatNumber rejects}}{{failsCount}}
{{url}}{{formatNumber accepts}}{{formatNumber rejects}}{{failsCount}}
+ Status: {{info.status}} + Height: {{info.height}} + Tx Pool Size: {{info.tx_pool_size}} + In: {{info.incoming_connections_count}} + Out: {{info.outgoing_connections_count}} +