Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc: Add support for batched requests/responses #3534

Merged
merged 40 commits into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
f17f68d
Add JSON RPC batching for client and server
thanethomson Feb 8, 2019
1ba2d2b
Add additional checks to ensure client responses are the same as results
thanethomson Feb 8, 2019
9968d77
Fix case where a notification is sent and no response is expected
thanethomson Feb 8, 2019
bfbea9e
Add test to check that JSON RPC notifications in a batch are left out…
thanethomson Feb 8, 2019
8da4e5f
Update CHANGELOG_PENDING.md
thanethomson Feb 8, 2019
987b7e3
Merge changes from develop and fix minor conflicts
thanethomson Apr 8, 2019
8dd2798
Update PR number now that PR has been created
thanethomson Apr 8, 2019
fafb9b4
Make errors start with lowercase letter
thanethomson Apr 9, 2019
c1142b3
Refactor batch functionality to be standalone
thanethomson Apr 9, 2019
ac4b542
Add examples for simple and batch HTTP client usage
thanethomson Apr 9, 2019
5f77f9b
Check errors from writer and remove nolinter directives
thanethomson Apr 10, 2019
5ec984c
Make error strings start with lowercase letter
thanethomson Apr 10, 2019
b2dae9c
Refactor examples to make them testable
thanethomson Apr 10, 2019
07490bc
Use safer deferred shutdown for example Tendermint test node
thanethomson Apr 10, 2019
a17e0c3
Recompose rpcClient interface from pre-existing interface components
thanethomson Apr 11, 2019
1a84723
Rename WaitGroup for brevity
thanethomson Apr 11, 2019
197145c
Replace empty ID string with request ID
thanethomson Apr 11, 2019
7fee75e
Remove extraneous test case
thanethomson Apr 11, 2019
03559e4
Convert first letter of errors.Wrap() messages to lowercase
thanethomson Apr 11, 2019
96205a9
Remove extraneous function parameter
thanethomson Apr 11, 2019
5b49ebe
Make variable declaration terse
thanethomson Apr 11, 2019
acfc63e
Reorder WaitGroup.Done call to help prevent race conditions in the fa…
thanethomson Apr 11, 2019
bce06d3
Merge latest changes from develop
thanethomson Apr 11, 2019
56e0a8d
Swap mutex to value representation and remove initialization
thanethomson Apr 11, 2019
73947cc
Restore empty JSONRPC string ID in response to prevent nil
thanethomson Apr 11, 2019
74bad45
Make JSONRPCBufferedRequest private
thanethomson Apr 11, 2019
cdd4398
Revert PR hard link in CHANGELOG_PENDING
thanethomson Apr 12, 2019
9d2fb41
Add client ID for JSONRPCClient
thanethomson Apr 12, 2019
6fbbdbf
Merge latest changes from develop and fix CHANGELOG_PENDING
thanethomson Apr 15, 2019
5575008
Extract response ID validation into separate function
thanethomson Apr 15, 2019
9c1d168
Remove extraneous comments
thanethomson Apr 16, 2019
82d81a4
Reorder fields to indicate clearly which are protected by the mutex
thanethomson Apr 16, 2019
1a42fa4
Refactor for loop to remove indexing
thanethomson Apr 16, 2019
68b8451
Restructure and combine loop
thanethomson Apr 16, 2019
3a7e84a
Flatten conditional block for better readability
thanethomson Apr 16, 2019
2432b42
Make multi-variable declaration slightly more readable
thanethomson Apr 16, 2019
dabe533
Change for loop style
thanethomson Apr 16, 2019
ed43944
Compress error check statements
thanethomson Apr 16, 2019
00062c7
Make function description more generic to show that we support differ…
thanethomson Apr 16, 2019
256d071
Preallocate memory for request and result objects
thanethomson Apr 17, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
### FEATURES:

### IMPROVEMENTS:
- [rpc] [\#3534](https://github.com/tendermint/tendermint/pull/3534) Add support for batched requests/responses in JSON RPC

### BUG FIXES:
126 changes: 126 additions & 0 deletions rpc/client/examples_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package client_test

import (
"bytes"
"fmt"

"github.com/tendermint/tendermint/abci/example/kvstore"
"github.com/tendermint/tendermint/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
rpctest "github.com/tendermint/tendermint/rpc/test"
)

func ExampleHTTP_simple() {
melekes marked this conversation as resolved.
Show resolved Hide resolved
// Start a tendermint node (and kvstore) in the background to test against
app := kvstore.NewKVStoreApplication()
node := rpctest.StartTendermint(app, rpctest.SuppressStdout, rpctest.RecreateConfig)
defer rpctest.StopTendermint(node)

// Create our RPC client
rpcAddr := rpctest.GetConfig().RPC.ListenAddress
c := client.NewHTTP(rpcAddr, "/websocket")

// Create a transaction
k := []byte("name")
v := []byte("satoshi")
tx := append(k, append([]byte("="), v...)...)

// Broadcast the transaction and wait for it to commit (rather use
// c.BroadcastTxSync though in production)
bres, err := c.BroadcastTxCommit(tx)
if err != nil {
panic(err)
}
if bres.CheckTx.IsErr() || bres.DeliverTx.IsErr() {
panic("BroadcastTxCommit transaction failed")
}

// Now try to fetch the value for the key
qres, err := c.ABCIQuery("/key", k)
if err != nil {
panic(err)
}
if qres.Response.IsErr() {
panic("ABCIQuery failed")
}
if !bytes.Equal(qres.Response.Key, k) {
panic("returned key does not match queried key")
}
if !bytes.Equal(qres.Response.Value, v) {
panic("returned value does not match sent value")
}

fmt.Println("Sent tx :", string(tx))
fmt.Println("Queried for :", string(qres.Response.Key))
fmt.Println("Got value :", string(qres.Response.Value))

// Output:
// Sent tx : name=satoshi
// Queried for : name
// Got value : satoshi
thanethomson marked this conversation as resolved.
Show resolved Hide resolved
}

func ExampleHTTP_batching() {
melekes marked this conversation as resolved.
Show resolved Hide resolved
// Start a tendermint node (and kvstore) in the background to test against
app := kvstore.NewKVStoreApplication()
node := rpctest.StartTendermint(app, rpctest.SuppressStdout, rpctest.RecreateConfig)
defer rpctest.StopTendermint(node)

// Create our RPC client
rpcAddr := rpctest.GetConfig().RPC.ListenAddress
c := client.NewHTTP(rpcAddr, "/websocket")

// Create our two transactions
k1 := []byte("firstName")
v1 := []byte("satoshi")
tx1 := append(k1, append([]byte("="), v1...)...)

k2 := []byte("lastName")
v2 := []byte("nakamoto")
tx2 := append(k2, append([]byte("="), v2...)...)

txs := [][]byte{tx1, tx2}

// Create a new batch
batch := c.NewBatch()

// Queue up our transactions
for _, tx := range txs {
if _, err := batch.BroadcastTxCommit(tx); err != nil {
panic(err)
}
}

// Send the batch of 2 transactions
if _, err := batch.Send(); err != nil {
panic(err)
}

// Now let's query for the original results as a batch
keys := [][]byte{k1, k2}
for _, key := range keys {
if _, err := batch.ABCIQuery("/key", key); err != nil {
panic(err)
}
}

// Send the 2 queries and keep the results
results, err := batch.Send()
if err != nil {
panic(err)
}

// Each result in the returned list is the deserialized result of each
// respective ABCIQuery response
for _, result := range results {
qr, ok := result.(*ctypes.ResultABCIQuery)
if !ok {
panic("invalid result type from ABCIQuery request")
}
fmt.Println(string(qr.Response.Key), "=", string(qr.Response.Value))
}

// Output:
// firstName = satoshi
// lastName = nakamoto
}
2 changes: 1 addition & 1 deletion rpc/client/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Waiter func(delta int64) (abort error)
// but you can plug in another one
func DefaultWaitStrategy(delta int64) (abort error) {
if delta > 10 {
return errors.Errorf("Waiting for %d blocks... aborting", delta)
return errors.Errorf("waiting for %d blocks... aborting", delta)
} else if delta > 0 {
// estimate of wait time....
// wait half a second for the next block (in progress)
Expand Down