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

Add Batch JSON-RPC support (rpc client & server) #1583

Merged
merged 1 commit into from
Feb 9, 2021

Conversation

jakesylvestre
Copy link
Collaborator

@jakesylvestre jakesylvestre commented May 22, 2020

This pr aims to address #329 which has been open for a while now by adding bulk request support. This is based on from decred#841 by @davecgh

Note: This PR was previously accidentally merged in #1503 and reverted in #1549 (followed by a rebase to clean up the commit history) and as a result, there is considerable discussion at #1503

In regards to the multiple commits: once we have consensus on the implementation I'll rebase into a single commit

@jakesylvestre
Copy link
Collaborator Author

Rebased!

@jakesylvestre
Copy link
Collaborator Author

Also - adding some changes from #1503. There were like 30 commits before so I wanted to squash, but I'll rebase again when we want to merge

@jakesylvestre
Copy link
Collaborator Author

jakesylvestre commented Aug 29, 2020

@everyone sorry about the fractal nature, trying to address everyone's reviews on the old pr.

@torkelrogstad curious why the custom type here would be better than a string. This allows us to use new versions without modifying the code:

image

Happy to implement this if there's a reason to. If we did, I'd like a validator that we can call to make sure the string conforms to the type. Something like

(rpcVersion) isValid(){
  // check if one of valid versions
}

The implementation would look like this:
image

The reason I didn't implement it this way is method is not a type right now

@jakesylvestre
Copy link
Collaborator Author

jakesylvestre commented Aug 29, 2020

also @jcvernaleo @onyb @torkelrogstad @Roasbeef I just moved all the reviewers over from #1503 feel free to remove/add yourself (I can't add you if you're not a participant in the issue)

@jakesylvestre
Copy link
Collaborator Author

jakesylvestre commented Aug 29, 2020

@torkelrogstad implemented your change in 4a97be3, I can revert if we want to. I still think if this is done method should be a custom type as well. #1596 does this with ChangeType so makes sense to be consistent

@onyb onyb added this to the 0.22.0 milestone Sep 7, 2020
Copy link
Collaborator

@onyb onyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I have carefully reviewed most of the PR but may come back at it again later.

Can you please add some batch JSON-RPC tests to integration/rpcserver_test.go?

.gitignore Outdated Show resolved Hide resolved
config.go Outdated Show resolved Hide resolved
goclean.sh Outdated Show resolved Hide resolved
Comment on lines 12 to 37
type RpcVersion string

const (
// version 1 of rpc
RpcVersion1 RpcVersion = RpcVersion("1.0")
// version 2 of rpc
RpcVersion2 RpcVersion = RpcVersion("2.0")
)

var validRpcVersions = []RpcVersion{RpcVersion1, RpcVersion2}

// check if the rpc version is a valid version
func (r RpcVersion) IsValid() bool {
for _, version := range validRpcVersions {
if version == r {
return true
}
}
return false
}

// cast rpc version to a string
func (r RpcVersion) String() string {
return string(r)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this whole block is a bit superfluous. The most useful part of this is perhaps the IsValid() method, and currently it is used like this:

version = RpcVersion(maybeEvilJsonRpcVersion)
if !version.IsValid()

First of all, using types for RpcVersion doesn't give us much type-safety. So instead of this:

btcjson.MarshalCmd(btcjson.RpcVersion1, ...)

we can also do this, and the compiler will be fine with it:

btcjson.MarshalCmd("3.0", ...)

Instead, why not have a simple function that checks the string version like this:

func IsRpcVersionValid(version string) bool {
        // do the check
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also golint recommends RPCVersion as opposed to RpcVersion.

Copy link
Collaborator Author

@jakesylvestre jakesylvestre Dec 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@onyb This was done to address @torkelrogstad's comment here #1503 (comment). I'm happy to change it back, but it seemed like typed constants were preferred. I added some brief comments on this here: #1583 (comment) and here: #1583 (comment)

I've added the golint reccomendation

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not so important. Let's keep it this way - at least it improves readability.

btcjson/jsonrpc.go Outdated Show resolved Hide resolved
rpcclient/infrastructure.go Outdated Show resolved Hide resolved
rpcclient/infrastructure.go Outdated Show resolved Hide resolved
rpcclient/infrastructure.go Outdated Show resolved Hide resolved
rpcserver.go Outdated Show resolved Hide resolved
rpcserver.go Outdated Show resolved Hide resolved
@jcvernaleo
Copy link
Member

Looking pretty good. Needs rebase, comments from @onyb addressed, and then squash.

if err != nil {
return nil, err
}
var arr []IndividualBulkResult
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res may have a different structure. Example:

{"result":null,"error":{"code":-32700,"message":"Parse error"},"id":null}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't this be: [{"result":null,"error":{"code":-32700,"message":"Parse error"},"id":null}]?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember how I encountered it, but it was during some tests. I can try to reproduce it again.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering why these changes are required to begin with? Maybe you forgot to remove these changes?

rpcclient/chain.go Outdated Show resolved Hide resolved
@coveralls
Copy link

coveralls commented Dec 1, 2020

Pull Request Test Coverage Report for Build 494215604

  • 86 of 725 (11.86%) changed or added relevant lines in 8 files are covered.
  • 20 unchanged lines in 4 files lost coverage.
  • Overall coverage increased (+1.1%) to 52.799%

Changes Missing Coverage Covered Lines Changed/Added Lines %
rpcclient/rawrequest.go 0 1 0.0%
integration/rpctest/rpc_harness.go 28 31 90.32%
btcjson/jsonrpc.go 49 66 74.24%
rpcclient/infrastructure.go 0 115 0.0%
rpcserver.go 0 192 0.0%
rpcwebsocket.go 0 311 0.0%
Files with Coverage Reduction New Missed Lines %
rpcclient/infrastructure.go 2 0%
btcec/signature.go 3 92.48%
rpcwebsocket.go 4 0.16%
peer/peer.go 11 75.47%
Totals Coverage Status
Change from base Build 407350020: 1.1%
Covered Lines: 20881
Relevant Lines: 39548

💛 - Coveralls

Copy link
Collaborator Author

@jakesylvestre jakesylvestre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs rebase.

Also just a misc comment:

It's pretty hard to tell what our actual coverage looks like with the current way the rpc harness is setup (spawning a new process). It's even harder to use a debugger - it'd be nice to figure out a nicer way to do that

if err != nil {
return nil, err
}
var arr []IndividualBulkResult
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't this be: [{"result":null,"error":{"code":-32700,"message":"Parse error"},"id":null}]?

@jakesylvestre
Copy link
Collaborator Author

jakesylvestre commented Dec 1, 2020

Alright, so I think I've addressed all the comments here other than this ongoing debate. Huge thanks to @onyb for the comprehensive review and let me know what else here needs cleanup

integration/rpcserver_test.go Outdated Show resolved Hide resolved
integration/rpcserver_test.go Outdated Show resolved Hide resolved
integration/rpctest/rpc_harness.go Show resolved Hide resolved
btcjson/jsonrpc.go Show resolved Hide resolved
}

// The JSON-RPC 1.0 spec defines that notifications must have their "id"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems a lot of code on the left-side has been removed. Can you please explain this part?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of the validations been moved further down the tree since it only applied to 1.0 rpc

Comment on lines 12 to 37
type RpcVersion string

const (
// version 1 of rpc
RpcVersion1 RpcVersion = RpcVersion("1.0")
// version 2 of rpc
RpcVersion2 RpcVersion = RpcVersion("2.0")
)

var validRpcVersions = []RpcVersion{RpcVersion1, RpcVersion2}

// check if the rpc version is a valid version
func (r RpcVersion) IsValid() bool {
for _, version := range validRpcVersions {
if version == r {
return true
}
}
return false
}

// cast rpc version to a string
func (r RpcVersion) String() string {
return string(r)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not so important. Let's keep it this way - at least it improves readability.

Copy link
Collaborator

@onyb onyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding my last set of review comments. They are mostly minor ones. Looking really good so far, and I can see the light at the end of the tunnel.

While you address the remaining comments, I'll try to take some time and do some QA.

@jakesylvestre
Copy link
Collaborator Author

should be all set with those changes. Let me know if you need a little more clarity here - #1583 (comment). I was a little unclear on the block you were referring too

integration/rpcserver_test.go Outdated Show resolved Hide resolved
if err != nil {
return nil, err
}
var arr []IndividualBulkResult
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering why these changes are required to begin with? Maybe you forgot to remove these changes?

rpcclient/infrastructure.go Show resolved Hide resolved
rpcserver.go Show resolved Hide resolved
@jakesylvestre
Copy link
Collaborator Author

jakesylvestre commented Feb 4, 2021

btw - did a little load testing on this. Works great
image

@jakesylvestre
Copy link
Collaborator Author

Hey, what do we need to get this in?

Copy link
Collaborator

@onyb onyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unable to resolve conversations on this PR, but it seems all review comments have been addressed/answered. I did some quick tests on my side, and it works great.

Congrats on making it to the end! 🚀

Copy link
Member

@jcvernaleo jcvernaleo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

This is awesome. Nice work.

And good job from all the reviewers too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[rpc] Add support for JSON-RPC 2.0 batch requests
6 participants