Skip to content

Streamlining batch_call and removing unnecessary unwraps() - #34

Merged
afilini merged 2 commits into
bitcoindevkit:masterfrom
BP-WG:fix/batch_call
Apr 13, 2021
Merged

afilini merged 2 commits into
bitcoindevkit:masterfrom
BP-WG:fix/batch_call

Conversation

@dr-orlovsky

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

Copy link
Copy Markdown
Contributor

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
Comment thread src/raw_client.rs Outdated
let mut guard = self
.waiting_map
.lock()
.map_err(|_| Error::CouldntLockReader)?;

Copy link
Copy Markdown
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

Comment thread src/raw_client.rs Outdated
.waiting_map
.lock()
.map_err(|_| Error::CouldntLockReader)?;
guard.remove(&req_id);

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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);
}

Comment thread src/raw_client.rs Outdated
Ok(resp) => {
let mut res = resp
.get("result")
.cloned()

Copy link
Copy Markdown
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

Comment thread src/raw_client.rs Outdated
let answer = answer.into_iter().map(|mut x| x["result"].take()).collect();

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

Copy link
Copy Markdown
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
Copy Markdown
Contributor Author

Fixed according to suggestions & improved

Comment thread src/raw_client.rs Outdated
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
Copy Markdown
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.

@dr-orlovsky dr-orlovsky Apr 12, 2021 •

Copy link
Copy Markdown
Contributor Author

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