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