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

feat(client): support request id as Strings. #659

Merged
merged 7 commits into from
Jan 21, 2022

Conversation

niklasad1
Copy link
Member

@niklasad1 niklasad1 commented Jan 19, 2022

Supersedes #644

It makes it possible to configure the clients to generate request object ID as a strings instead of numbers, I did the most simple way and converting the numeric ID to strings from the RequestIdManager.

We might want to use some more optimized itoa instead of format in future or generate random IDs.

However, numeric ids is still default because it avoids some allocations.

The rationale behind this is that some JSON-RPC servers suffers from the issue where they can't decode Id as numbers because of the serde-json arbritary-precision bug, so this is a workaround for that.

//cc @whalelephant I think this should be what you need right?

@niklasad1 niklasad1 requested a review from a team as a code owner January 19, 2022 10:00
Copy link
Contributor

@dvdplm dvdplm left a comment

Choose a reason for hiding this comment

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

Feels like RequestIdManager could be a bit smarter about the IDs, and be configured to use the right IdKind so that other code doesn't have to do the transformation itself. Or is that very annoying to do?

client/http-client/src/client.rs Outdated Show resolved Hide resolved
client/http-client/src/client.rs Outdated Show resolved Hide resolved
client/ws-client/src/lib.rs Outdated Show resolved Hide resolved
core/src/client/async_client/mod.rs Outdated Show resolved Hide resolved
@niklasad1
Copy link
Member Author

Feels like RequestIdManager could be a bit smarter about the IDs, and be configured to use the right IdKind so that other code doesn't have to do the transformation itself. Or is that very annoying to do?

Sounds reasonable to me, I did the most naive way I could think of to test that it worked so sure shouldn't be that hard I think

fn into_id(self, id: u64) -> Id<'static> {
match self {
IdKind::Number => Id::Number(id),
IdKind::String => Id::Str(format!("{}", id).into()),
Copy link
Member Author

Choose a reason for hiding this comment

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

we could probably use some optimized itoa or something but should fast enough I guess for now...

Copy link
Contributor

@maciejhirsz maciejhirsz Jan 21, 2022

Choose a reason for hiding this comment

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

Could also subslice byte array of all numbers from 00 to 99 as a static Cow (for values < 100), but yeah, this is good enough :).

@whalelephant
Copy link

Hi @niklasad1,

Yes, this includes what I was looking for. Thank you!

@@ -350,7 +350,7 @@ impl<'a> SubscriptionId<'a> {
}

/// Request Id
#[derive(Debug, PartialEq, Clone, Hash, Eq, Deserialize, Serialize)]
#[derive(Debug, PartialEq, Clone, Hash, Eq, Deserialize, Serialize, PartialOrd, Ord)]
#[serde(deny_unknown_fields)]
#[serde(untagged)]
pub enum Id<'a> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I didn't notice offhand; is a borrowed version of an ID ever used here? I pretty much assume every new ID will need to be an owned variant anyway. so I wonder how useful the lifetime/Cow is?

(thinking down that line, in general any serde_json::Value could be returned as an ID (whether or not certain values make sense, who knows) so I was wondering whether using that here would simplify anything)

Copy link
Member Author

@niklasad1 niklasad1 Jan 20, 2022

Choose a reason for hiding this comment

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

I think you are right at least in the point of view for the client.

However, I think we actually can use the lifetime and do zero-copy deserialization both in the servers (on new request) and clients (on the responses) with #[serde(borrow)]

Copy link
Collaborator

@jsdw jsdw left a comment

Choose a reason for hiding this comment

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

LGTM!


#[test]
fn request_id_guard_works() {
let manager = RequestIdManager::new(2);
let manager = RequestIdManager::new(2, IdKind::Number);
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to have a test where IdKind::String, not sure if this is covered elsewhere residually though.

Copy link
Member Author

@niklasad1 niklasad1 Jan 21, 2022

Choose a reason for hiding this comment

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

I think that's covered by some unit tests for the whole ws client but wouldn't hurt with a unit test for String also I suppose :)

However, the important thing is the Arc which is independent of the actual id.

@niklasad1 niklasad1 merged commit 708d421 into master Jan 21, 2022
@niklasad1 niklasad1 deleted the na-clients-support-reqid-as-string branch January 21, 2022 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants