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

Streamlining batch_call and removing unnecessary unwraps() #34

Merged
merged 2 commits into from
Apr 13, 2021

Conversation

dr-orlovsky
Copy link
Contributor

@dr-orlovsky dr-orlovsky commented Jan 21, 2021

This improves overall function code style & allows to remove two unnecessary unwraps and one implicit panic. Together with #33 this makes this library unwrap-free and stable (i.e. not causing the software using it to unexpectedly terminate instead or reporting error to the calling function)

@dr-orlovsky dr-orlovsky force-pushed the fix/batch_call branch 2 times, most recently from b943c56 to 02462b3 Compare January 21, 2021 01:13
let mut guard = self
.waiting_map
.lock()
.map_err(|_| Error::CouldntLockReader)?;
Copy link
Member

Choose a reason for hiding this comment

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

Same as in #33, this needs a specific error

.waiting_map
.lock()
.map_err(|_| Error::CouldntLockReader)?;
guard.remove(&req_id);
Copy link
Member

Choose a reason for hiding this comment

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

I think I'm missing something, why did you remove the loop here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep,my bad, I haven't understood the code and thought req_id is an external variable. Will fix. Now I see why you was maintaining list of missing responses up to date.

In general, can you explain what actually should happen here? What should be a consequences of erroring one of the batch request? Cancellation of the rest of the requests and returning single error, ignoring all ok-requests already received? That does not make a lot of sense for me... May be I am missing something?

Copy link
Member

Choose a reason for hiding this comment

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

Right now if one request fails it makes the whole batch fail. If there are still some requests pending it will just ignore their response when they come back (there's no way of cancelling a request you've already sent).

This line specifically is where all the pending requests id are removed from the map of responses we are waiting for, which means that once the response comes in the current reader_thread will just ignore it:

if let Some(sender) = self.waiting_map.lock().unwrap().remove(&resp_id)
{
sender
.send(ChannelMessage::Response(resp))
.expect("Unable to send the response");
} else {
warn!("Missing listener for {}", resp_id);
}

Ok(resp) => {
let mut res = resp
.get("result")
.cloned()
Copy link
Member

Choose a reason for hiding this comment

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

I would keep this part as it was before, just take()-ing the result and adding it to answer.

There's no need to return an InvalidResponse here because if there's something wrong with it we'll just see that later when trying to parse the response into a specific struct.

I guess if you really wanted to return that error instead of a generic serde error you could add this to impl_batch_call:

answer.push(serde_json::from_value(x)?);

You could map the error here to InvalidResponse before returning it

let answer = answer.into_iter().map(|mut x| x["result"].take()).collect();

Ok(answer)
Ok(answers.into_iter().map(|(_, item)| item).collect())
Copy link
Member

Choose a reason for hiding this comment

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

I think you are missing the part where you remove the id of the response we've just received from missing_responses.

@dr-orlovsky
Copy link
Contributor Author

Fixed according to suggestions & improved

for req_id in missing_responses.iter() {
match self.recv(&receiver, *req_id) {
Ok(mut resp) => answers.insert(
resp["id"].as_u64().unwrap_or_default(),
Copy link
Member

Choose a reason for hiding this comment

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

I'm not entirely sure unwrap_or_default() is a good idea here: in theory if we got to this point it means that the response had an id, but in case it's missing assuming its value is 0 can create issues. I think it would be better to replace it with .unwrap_or(req_id), or even just always returning the req_id directly.

Copy link
Contributor Author

@dr-orlovsky dr-orlovsky Apr 12, 2021

Choose a reason for hiding this comment

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

You are right. Fixed in cfc7bfe

@afilini afilini merged commit cfc7bfe into bitcoindevkit:master Apr 13, 2021
@dr-orlovsky dr-orlovsky deleted the fix/batch_call branch April 13, 2021 13:43
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.

2 participants