feat_: Add timeout to callprivaterpc endpoint
This commit is contained in:
parent
dfdc1652a2
commit
c592bef3d1
|
@ -3,6 +3,7 @@ package rpc
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
gethrpc "github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
@ -38,6 +39,7 @@ type jsonrpcRequest struct {
|
|||
ChainID uint64 `json:"chainId"`
|
||||
Method string `json:"method"`
|
||||
Params json.RawMessage `json:"params,omitempty"`
|
||||
Timeout uint64 `json:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
type jsonrpcSuccessfulResponse struct {
|
||||
|
@ -111,11 +113,28 @@ func (c *Client) callBatchMethods(ctx context.Context, msgs json.RawMessage) str
|
|||
// callSingleMethod executes single JSON-RPC message and constructs proper response.
|
||||
func (c *Client) callSingleMethod(ctx context.Context, msg json.RawMessage) string {
|
||||
// unmarshal JSON body into json-rpc request
|
||||
chainID, method, params, id, err := methodAndParamsFromBody(msg)
|
||||
jsonrpcParams, err := methodAndParamsFromBody(msg)
|
||||
if err != nil {
|
||||
return newErrorResponse(errInvalidMessageCode, err, id)
|
||||
return newErrorResponse(errInvalidMessageCode, err, nil)
|
||||
}
|
||||
|
||||
chainID := jsonrpcParams.ChainID
|
||||
method := jsonrpcParams.Method
|
||||
params := jsonrpcParams.Params
|
||||
timeout := jsonrpcParams.Timeout
|
||||
id := jsonrpcParams.ID
|
||||
|
||||
if timeout != 0 {
|
||||
// TODO: remove me
|
||||
c.log.Info("setting 50ms timeout", "method", method)
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout)*time.Millisecond)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
// TODO: remove me
|
||||
c.log.Info("calling method", "method", method)
|
||||
|
||||
if chainID == 0 {
|
||||
chainID = c.UpstreamChainID
|
||||
}
|
||||
|
@ -139,24 +158,38 @@ func (c *Client) callSingleMethod(ctx context.Context, msg json.RawMessage) stri
|
|||
return newSuccessResponse(result, id)
|
||||
}
|
||||
|
||||
type jsonrpcParameters struct {
|
||||
ChainID uint64
|
||||
Method string
|
||||
Params []interface{}
|
||||
Timeout uint64
|
||||
ID json.RawMessage
|
||||
}
|
||||
|
||||
// methodAndParamsFromBody extracts Method and Params of
|
||||
// JSON-RPC body into values ready to use with ethereum-go's
|
||||
// RPC client Call() function. A lot of empty interface usage is
|
||||
// due to the underlying code design :/
|
||||
func methodAndParamsFromBody(body json.RawMessage) (uint64, string, []interface{}, json.RawMessage, error) {
|
||||
func methodAndParamsFromBody(body json.RawMessage) (*jsonrpcParameters, error) {
|
||||
msg, err := unmarshalMessage(body)
|
||||
if err != nil {
|
||||
return 0, "", nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
params := []interface{}{}
|
||||
if msg.Params != nil {
|
||||
err = json.Unmarshal(msg.Params, ¶ms)
|
||||
if err != nil {
|
||||
return 0, "", nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return msg.ChainID, msg.Method, params, msg.ID, nil
|
||||
return &jsonrpcParameters{
|
||||
ChainID: msg.ChainID,
|
||||
Method: msg.Method,
|
||||
Params: params,
|
||||
Timeout: msg.Timeout,
|
||||
ID: msg.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// unmarshalMessage tries to unmarshal JSON-RPC message.
|
||||
|
|
|
@ -59,6 +59,7 @@ func TestMethodAndParamsFromBody(t *testing.T) {
|
|||
id json.RawMessage
|
||||
chainID uint64
|
||||
shouldFail bool
|
||||
timeout uint64
|
||||
}{
|
||||
{
|
||||
"params_array",
|
||||
|
@ -73,6 +74,7 @@ func TestMethodAndParamsFromBody(t *testing.T) {
|
|||
json.RawMessage(`42`),
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"params_empty_array",
|
||||
|
@ -82,6 +84,7 @@ func TestMethodAndParamsFromBody(t *testing.T) {
|
|||
nil,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"params_none",
|
||||
|
@ -91,6 +94,7 @@ func TestMethodAndParamsFromBody(t *testing.T) {
|
|||
nil,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"params_chain_id",
|
||||
|
@ -100,6 +104,7 @@ func TestMethodAndParamsFromBody(t *testing.T) {
|
|||
nil,
|
||||
2,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"getFilterMessage",
|
||||
|
@ -109,6 +114,7 @@ func TestMethodAndParamsFromBody(t *testing.T) {
|
|||
json.RawMessage(`44`),
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"getFilterMessage_array",
|
||||
|
@ -118,6 +124,7 @@ func TestMethodAndParamsFromBody(t *testing.T) {
|
|||
nil,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"empty_array",
|
||||
|
@ -127,21 +134,33 @@ func TestMethodAndParamsFromBody(t *testing.T) {
|
|||
nil,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"timeout",
|
||||
json.RawMessage(`{"jsonrpc": "2.0", "timeout": 2000, "method": "test"}`),
|
||||
[]interface{}{},
|
||||
"test",
|
||||
nil,
|
||||
0,
|
||||
false,
|
||||
2000,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
chainID, method, params, id, err := methodAndParamsFromBody(test.body)
|
||||
response, err := methodAndParamsFromBody(test.body)
|
||||
if test.shouldFail {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.chainID, chainID)
|
||||
require.Equal(t, test.method, method)
|
||||
require.Equal(t, test.params, params)
|
||||
require.EqualValues(t, test.id, id)
|
||||
require.Equal(t, test.timeout, response.Timeout)
|
||||
require.Equal(t, test.chainID, response.ChainID)
|
||||
require.Equal(t, test.method, response.Method)
|
||||
require.Equal(t, test.params, response.Params)
|
||||
require.EqualValues(t, test.id, response.ID)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue