-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
API versioning #3155
API versioning #3155
Conversation
How about a versioning scheme similar to Kubernetes objects where also a readiness is encoded (Alpha, Beta...)? Just an integer is a bit weak... |
In my opinion, any API version that appears in a stable release of rippled is “ready”. I don’t think there’s a need for the additional complexity that comes with alpha/beta distinctions. |
Codecov Report
@@ Coverage Diff @@
## develop #3155 +/- ##
==========================================
+ Coverage 68.94% 69% +0.06%
==========================================
Files 688 688
Lines 55743 55799 +56
==========================================
+ Hits 38432 38506 +74
+ Misses 17311 17293 -18
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Left some comments, mostly nits that are at your discretion. I'll give you a chance to consider the feedback and come back to give this a second look and sign-off on it tomorrow.
src/ripple/rpc/impl/RPCHelpers.cpp
Outdated
} | ||
} | ||
return RPC::APIInvalidVersion; | ||
} else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This takes advantage of code that already exists in Json::Value
. I like it but I'm not sure if I like it enough, especially when you consider that we will be eventually be migrating to this when it's merged into Boost. Anyways, something for you to consider:
unsigned int getAPIVersionNumber(Json::Value const& jv)
{
static Json::Value const minVersion (RPC::APIVersionSupportedRangeLow);
static Json::Value const maxVersion (RPC::APIVersionSupportedRangeHigh);
static Json::Value const invalidVersion (RPC::APIInvalidVersion);
auto requestedVersion = jv.get (jss::api_version, Json::Value(RPC::APIVersionIfUnspecified));
if(requestedVersion < minVersion || requestedVersion > maxVersion)
v = invalidVersion;
return requestedVersion.asUInt();
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually my simplifcation doesn't quite work. It needs a further tweak.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modified it and added a unit test.
src/ripple/rpc/Context.h
Outdated
@@ -55,6 +55,7 @@ struct Context | |||
LedgerMaster& ledgerMaster; | |||
Resource::Consumer& consumer; | |||
Role role; | |||
unsigned apiVersion; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be unsigned int
(not just here, but everywhere).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I changed unsigned
to unsigned int
in all files in this PR.
src/ripple/rpc/impl/RPCHelpers.h
Outdated
|
||
constexpr unsigned APIInvalidVersion = 0; | ||
constexpr unsigned APIFirstVersion = 1; | ||
constexpr unsigned APIVersionSupportedRangeLow = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider:
APIVersionSupportedRangeLow
-> ApiMinimumSupportedVersion
APIVersionSupportedRangeHigh
-> ApiMaximumSupportedVersion
APIVersionIfUnspecified
-> ApiDefaultVersion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ApiMinimumSupportedVersion and ApiMaximumSupportedVersion are better names. I will change to them.
I used "ApiDefaultVersion" originally in the code too. But I feel we have two "Default Versions", (1) a network RPC request without specify a version which should default to version 1, (2) a command line request which I think should default to ApiMaximumSupportedVersion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ApiMinimumSupportedVersion
and ApiMaximumSupportedVersion
are changed.
APIVersionIfUnspecified
is not changed.
src/ripple/rpc/impl/RPCHelpers.h
Outdated
constexpr unsigned APIVersionSupportedRangeHigh = 1; | ||
constexpr unsigned APIVersionIfUnspecified = APIFirstVersion; | ||
constexpr unsigned APIVersionCommandLine = APIVersionSupportedRangeHigh; | ||
constexpr unsigned APIVersionRippledStartUp = APIVersionSupportedRangeHigh; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering that these two values are always likely to use a fixed version of the API, I wonder if defining values for them makes sense. We should probably just use RPC::APIVersionSupportedRangeLow
directly in the places where this is used and remove APIVersionCommandLine
and APIVersionRippledStartUp
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove APIVersionCommandLine and APIVersionRippledStartUp.
Just to confirm, we will use APIVersionSupportedRangeLow as the command line request version. I can see the benefit of both "high" and "low.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can argue for either low or high. I'm fine with using whatever is appropriate and leave that up to your judgement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed APIVersionCommandLine
and APIVersionRippledStartUp
, and used "high" for command line requests' versions.
Thanks, I will work on it.
…On Thu, Nov 21, 2019, 1:24 AM Nik Bougalis ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/ripple/rpc/impl/RPCHelpers.cpp
<#3155 (comment)>:
> @@ -716,5 +716,23 @@ beast::SemanticVersion const firstVersion("1.0.0");
beast::SemanticVersion const goodVersion("1.0.0");
beast::SemanticVersion const lastVersion("1.0.0");
+unsigned getAPIVersionNumber(const Json::Value & jv)
+{
+ if (jv.isMember(jss::api_version))
+ {
+ if(jv[jss::api_version].isInt())
+ {
+ unsigned apiVersion = jv[jss::api_version].asInt();
+ if(apiVersion >= RPC::APIVersionSupportedRangeLow &&
+ apiVersion <= RPC::APIVersionSupportedRangeHigh)
+ {
+ return apiVersion;
+ }
+ }
+ return RPC::APIInvalidVersion;
+ } else
Actually my simplifcation doesn't *quite* work. It needs a further tweak.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#3155>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACWTI7PSGCLGA3VISDNGL3QUYSRHANCNFSM4JMIVZLQ>
.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/ripple/net/impl/RPCCall.cpp
Outdated
if(jvRequest.isObject()) | ||
insert_api_version(jvRequest); | ||
else if(jvRequest.isArray()) { | ||
for (Json::UInt j = 0; j < jvRequest.size(); ++j) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the json arrays support range-based iteration, FWIW. Furthermore, since isMember
already checks isObject
, you can just just call std::for_each(jvRequest.begin(), jvRequest.end(), insert_api_version);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I changed to std::for_each(jvRequest.begin(), jvRequest.end(), insert_api_version);
I modified insert_api_version()
to include isObject()
. I think that is still needed. Otherwise, Value::operator[]
could be called on a non-object.
* Note that APIInvalidVersion will be returned if | ||
* 1) the version number field has a wrong format | ||
* 2) the version number retrieved is out of the supported range | ||
* 3) the version number is unspecified and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like case 3 should be covered by the static checks that @nbougalis suggested above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. But I think we need both the static check (checking we don't make a mistake in coding) and the check in the function (checking network requests are acceptable).
if (jsonRPC.isMember(jss::params) && | ||
jsonRPC[jss::params].isArray() && | ||
jsonRPC[jss::params].size() > 0 && | ||
jsonRPC[jss::params][Json::UInt(0)].isObject()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jsonRPC[jss::params][0u]....
might be little more concise (in general for indexing of json arrays with static values)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I changed the code.
src/test/rpc/RPCCall_test.cpp
Outdated
@@ -77,6 +79,7 @@ static RPCCallTestData const rpcCallTestArray [] = | |||
"method" : "account_channels", | |||
"params" : [ | |||
{ | |||
"api_version" : 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if I understand correctly, this version text/field is always replaced with the max supported (?). If that's the case, I would prefer just a token string here (e.g. %MAX_API_VER%
....) and then you search/replace that token in the update method (it gives a better sense of what's actually happening). If I've misunderstood what's going on, please ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks! I changed the code.
@pwang200, FWIW, I'm recusing myself from this code review. I have misgivings about the on-going indefinite maintenance effort that this change represents versus the benefit to users. Based on the conversations I've seen in other pull requests, I do not expect my concerns to be considered seriously at this point in time. I find myself unable to focus only on whether "an implementation has successfully realized its associated design" when I have reservations about the design itself. Rather than increase noise with no expected change in outcome I'll simply recuse myself. |
@pwang200 Has the consolidated documentation been created yet? |
The requirements are:
https://github.com/pwang200/RippledRPCDesign/blob/API_versioning/requirement/requirements.md
The design document is:
https://github.com/pwang200/RippledRPCDesign/blob/API_versioning/design/design.md
Note that the documentation is for informational only. We will consolidate the documentation and create another PR after both API Versioning and gRPC are merged.