Skip to content

Commit

Permalink
use provider of go-rpc-provider for hook CallContext/Call/BatchCallCo… (
Browse files Browse the repository at this point in the history
#179)

* use provider of go-rpc-provider for hook CallContext/Call/BatchCallContext/BatchCall/Subscribe
remove client_retry

* remove client_retry

* add context in CallRpcHandlerFunc/BatchCallRpcHandlerFunc for hook context when call/batchcall

* remove comments

* add changelog

* set default timeout to 3s

* restore default timeout to 30s

* nil
  • Loading branch information
wangdayong228 authored May 25, 2022
1 parent b255d35 commit 46cf769
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 183 deletions.
5 changes: 5 additions & 0 deletions changeLog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Go-conflux-sdk Change Log
============

v1.2.0
------------
- add context in CallRpcHandlerFunc/BatchCallRpcHandlerFunc for hook context when Call/Batchcall
> Note: It's not compatiable with previous version
V1.1.5
------------
- support setting max connection number for client with http(s) protocal
Expand Down
90 changes: 27 additions & 63 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package sdk

import (
"context"
"net/url"
"sync/atomic"

"math/big"
Expand All @@ -19,8 +18,9 @@ import (
"github.com/Conflux-Chain/go-conflux-sdk/types/cfxaddress"
sdkerrors "github.com/Conflux-Chain/go-conflux-sdk/types/errors"
postypes "github.com/Conflux-Chain/go-conflux-sdk/types/pos"
"github.com/mcuadros/go-defaults"
rpc "github.com/openweb3/go-rpc-provider"
"github.com/valyala/fasthttp"
providers "github.com/openweb3/go-rpc-provider/provider_wrapper"

"github.com/Conflux-Chain/go-conflux-sdk/utils"
"github.com/ethereum/go-ethereum/accounts/abi"
Expand Down Expand Up @@ -53,11 +53,11 @@ type ClientOption struct {
KeystorePath string
// retry
RetryCount int
RetryInterval time.Duration
RetryInterval time.Duration `default:"1s"`
// timeout of request
RequestTimeout time.Duration
RequestTimeout time.Duration `default:"30s"`
// Maximum number of connections may be established. The default value is 512. It's only useful for http(s) prococal
MaxConnectionNum int
MaxConnectionPerHost int
}

// NewClient creates an instance of Client with specified conflux node url, it will creat account manager if option.KeystorePath not empty.
Expand Down Expand Up @@ -90,7 +90,7 @@ func NewClient(nodeURL string, option ...ClientOption) (*Client, error) {
realOption = option[0]
}

client, err := newClientWithRetry(nodeURL, realOption)
client, err := newClientWithOption(nodeURL, realOption)
if err != nil {
return nil, errors.Wrap(err, "failed to new client with retry")
}
Expand All @@ -117,37 +117,25 @@ func NewClientWithRPCRequester(rpcRequester RpcRequester) (*Client, error) {
// NewClientWithRetry creates a retryable new instance of Client with specified conflux node url and retry options.
//
// the clientOption.RetryInterval will be set to 1 second if pass 0
func newClientWithRetry(nodeURL string, clientOption ClientOption) (*Client, error) {
func newClientWithOption(nodeURL string, clientOption ClientOption) (*Client, error) {

var client Client
defaults.SetDefaults(&clientOption)

client.nodeURL = nodeURL
client.option = clientOption
client.callRpcHandler = middleware.CallRpcHandlerFunc(client.callRpc)
client.batchCallRpcHandler = middleware.BatchCallRpcHandlerFunc(client.batchCallRPC)
client.callRpcHandler = middleware.CallRpcHandlerFunc(client.coreCallContext)
client.batchCallRpcHandler = middleware.BatchCallRpcHandlerFunc(client.coreBatchCallContext)

client.rpcPosClient = RpcPosClient{&client}
client.rpcTxpoolClient = RpcTxpoolClient{&client}
client.rpcDebugClient = RpcDebugClient{&client}
client.option.setDefault()

rpcClient, err := dialRpcClient(nodeURL, clientOption)
p, err := providers.NewProviderWithOption(nodeURL, *clientOption.genProviderOption())
if err != nil {
return nil, errors.Wrap(err, "failed to dial to fullnode")
}

if client.option.RetryCount == 0 {
client.rpcRequester = rpcClient
} else {
client.rpcRequester = &rpcClientWithRetry{
inner: rpcClient,
retryCount: client.option.RetryCount,
interval: client.option.RetryInterval,
}
}

_, err = client.GetNetworkID()
if err != nil {
return nil, errors.Wrap(err, "failed to get networkID")
return nil, errors.Wrap(err, "failed to new provider")
}
client.rpcRequester = p

if client.option.KeystorePath != "" {
am := NewAccountManager(client.option.KeystorePath, *client.networkID)
Expand All @@ -162,25 +150,8 @@ func newClientWithRetry(nodeURL string, clientOption ClientOption) (*Client, err
return &client, nil
}

func dialRpcClient(nodeURL string, clientOption ClientOption) (*rpc.Client, error) {
if u, err := url.Parse(nodeURL); err == nil {
if (u.Scheme == "http" || u.Scheme == "https") && clientOption.MaxConnectionNum > 0 {
fasthttpClient := new(fasthttp.Client)
fasthttpClient.MaxConnsPerHost = clientOption.MaxConnectionNum
return rpc.DialHTTPWithClient(nodeURL, fasthttpClient)
}
}
return rpc.Dial(nodeURL)
}

func (co *ClientOption) setDefault() {
if co.RequestTimeout == 0 {
co.RequestTimeout = time.Second * 30
}
// Interval 0 is meaningless and may lead full node busy, so default sets it to 1 second
if co.RetryInterval == 0 {
co.RetryInterval = time.Second
}
func (client *Client) Provider() RpcRequester {
return client.rpcRequester
}

// Pos returns RpcPosClient for invoke rpc with pos namespace
Expand Down Expand Up @@ -235,14 +206,10 @@ func (client *Client) MustNewAddress(base32OrHex string) types.Address {
//
// You could use UseCallRpcMiddleware to add middleware for hooking CallRPC
func (client *Client) CallRPC(result interface{}, method string, args ...interface{}) error {
return client.callRpcHandler.Handle(result, method, args...)
return client.callRpcHandler.Handle(context.Background(), result, method, args...)
}

func (client *Client) callRpc(result interface{}, method string, args ...interface{}) error {
ctx, cancelFunc := client.genContext()
if cancelFunc != nil {
defer cancelFunc()
}
func (client *Client) coreCallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
return client.rpcRequester.CallContext(ctx, result, method, args...)
}

Expand All @@ -262,15 +229,10 @@ func (client *Client) UseCallRpcMiddleware(middleware middleware.CallRpcMiddlewa
//
// You could use UseBatchCallRpcMiddleware to add middleware for hooking BatchCallRPC
func (client *Client) BatchCallRPC(b []rpc.BatchElem) error {
return client.batchCallRpcHandler.Handle(b)
return client.batchCallRpcHandler.Handle(context.Background(), b)
}

func (client *Client) batchCallRPC(b []rpc.BatchElem) error {
ctx, cancelFunc := client.genContext()
if cancelFunc != nil {
defer cancelFunc()
}

func (client *Client) coreBatchCallContext(ctx context.Context, b []rpc.BatchElem) error {
err := client.rpcRequester.BatchCallContext(ctx, b)
if err != nil {
return err
Expand Down Expand Up @@ -1369,9 +1331,11 @@ func get1stU64Ify(values []hexutil.Uint64) *hexutil.Uint64 {
return nil
}

func (client *Client) genContext() (context.Context, context.CancelFunc) {
if client.option.RequestTimeout > 0 {
return context.WithTimeout(context.Background(), client.option.RequestTimeout)
func (c *ClientOption) genProviderOption() *providers.Option {
return &providers.Option{
RequestTimeout: c.RequestTimeout,
RetryCount: c.RetryCount,
RetryInterval: c.RetryInterval,
MaxConnectionPerHost: c.MaxConnectionPerHost,
}
return context.Background(), nil
}
86 changes: 0 additions & 86 deletions client_retry.go

This file was deleted.

32 changes: 27 additions & 5 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ package sdk
// When rpc dail success
// Return client instance
import (
"context"
"fmt"
"testing"

. "bou.ke/monkey"
// "github.com/ethereum/go-ethereum/rpc"

rpc "github.com/openweb3/go-rpc-provider"
providers "github.com/openweb3/go-rpc-provider/provider_wrapper"
"github.com/pkg/errors"
. "github.com/smartystreets/goconvey/convey"
)
Expand All @@ -32,7 +35,7 @@ func _TestNewClient(t *testing.T) {
})
defer guard.Unpatch()

client, err := newClientWithRetry("", ClientOption{})
client, err := newClientWithOption("", ClientOption{})
Convey("Return error", func() {
So(err, ShouldNotEqual, nil)
So(client, ShouldEqual, nil)
Expand All @@ -46,22 +49,41 @@ func _TestNewClient(t *testing.T) {
})
defer guard.Unpatch()

client, err := newClientWithRetry("", ClientOption{})
client, err := newClientWithOption("", ClientOption{})
// fmt.Printf("client:%+v,err:%+v", client, err)

Convey("Return client instance", func() {
So(err, ShouldEqual, nil)
So(client, ShouldNotEqual, nil)
})

})

})

})

}

func TestInterfaceImplementation(t *testing.T) {
var _ ClientOperator = &Client{}
}

func TestClientHookCallContext(t *testing.T) {
c := MustNewClient("https://test.confluxrpc.com")
mp := c.Provider().(*providers.MiddlewarableProvider)
mp.HookCallContext(callContextMid1)
mp.HookCallContext(callContextMid2)
c.GetStatus()
}

func callContextMid1(f providers.CallContextFunc) providers.CallContextFunc {
return func(ctx context.Context, result interface{}, method string, args ...interface{}) error {
ctx = context.WithValue(ctx, "foo", "bar")
return f(ctx, result, method, args...)
}
}

func callContextMid2(f providers.CallContextFunc) providers.CallContextFunc {
return func(ctx context.Context, result interface{}, method string, args ...interface{}) error {
fmt.Printf("ctx value of foo: %+v\n", ctx.Value("foo"))
return f(ctx, result, method, args...)
}
}
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ require (
github.com/fatih/color v1.7.0
github.com/graph-gophers/graphql-go v1.3.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/openweb3/go-rpc-provider v0.1.2
github.com/openweb3/go-sdk-common v0.0.0-20220407083459-597b845413e8
github.com/mcuadros/go-defaults v1.2.0
github.com/openweb3/go-rpc-provider v0.2.0
github.com/openweb3/go-sdk-common v0.0.0-20220524083215-d22d44765e44
github.com/pkg/errors v0.9.1
github.com/shopspring/decimal v1.3.1
github.com/smartystreets/goconvey v1.6.4
github.com/stretchr/testify v1.7.0
github.com/valyala/fasthttp v1.33.0
gopkg.in/urfave/cli.v1 v1.20.0
gotest.tools v2.2.0+incompatible

)

// replace github.com/openweb3/go-sdk-common => ../go-sdk-common
// replace github.com/ethereum/go-ethereum => ../../ethereum/go-ethereum
// replace github.com/openweb3/go-rpc-provider v0.1.3 => ../go-rpc-provider
Loading

0 comments on commit 46cf769

Please sign in to comment.