-
Notifications
You must be signed in to change notification settings - Fork 42
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
Handle v2 error #474
Handle v2 error #474
Conversation
Pull Request Test Coverage Report for Build 12757549527Details
💛 - Coveralls |
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.
tACK 22a5281, though this seems like a great candidate for a new unit test.
payjoin-cli/src/app/v2.rs
Outdated
handle_request_error(e, receiver, &self.config.ohttp_relay).await?; | ||
unreachable!("handle_request_error always returns Err") |
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 feels counterintuitive, it might be clearer if handle_request_error
returns Ok(())
on success and this becomes:
handle_request_error(e, receiver, &self.config.ohttp_relay).await?; | |
unreachable!("handle_request_error always returns Err") | |
handle_request_error(e, receiver, &self.config.ohttp_relay).await?; | |
return Err(anyhow!("Failed to process proposal")); |
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 do think there is a change to make, that a successful handle_request_error returns the receive::Error which gets propagated via the question mark, but I think that second line should indeed be unreachable if that's the case because handle_request_error always returns an error. The reason the handle_request_error signature uses Result
is so that ?
can be used in the body. Is this still counterintuitive?
Perhaps using
/// Handle request error by sending an error response over the directory
async fn handle_request_error(
e: Error,
mut receiver: UncheckedProposal,
ohttp_relay: &payjoin::Url,
) -> anyhow::Error {
let (err_req, err_ctx) = match receiver.extract_err_req(&e, ohttp_relay) {
Ok(req_ctx) => req_ctx,
Err(e) => return anyhow!("Failed to extract error request: {}", e),
};
let err_response = match post_request(err_req).await {
Ok(response) => response,
Err(e) => return anyhow!("Failed to post error request: {}", e),
};
let err_bytes = match err_response.bytes().await {
Ok(bytes) => bytes,
Err(e) => return anyhow!("Failed to get error response bytes: {}", e),
};
if let Err(e) = receiver.process_err_res(&err_bytes, err_ctx) {
return anyhow!("Failed to process error response: {}", e);
}
e.into()
}
and
Err(e) => {
return Err(handle_request_error(e, receiver, &self.config.ohttp_relay).await);
}
makes more sense
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 seems better to me.
How would you unit test this? Manually produce a receive::error::Error and match it with a Receiver? I've been hacking around an integration test for this but it's lengthy and ugly |
22a5281
to
7813de0
Compare
I think we could start with a simple unit test that hardcodes an // copied from receive::v1::test
let original_psbt = "cHNidP8BAHMCAAAAAY8nutGgJdyYGXWiBEb45Hoe9lWGbkxh/6bNiOJdCDuDAAAAAAD+////AtyVuAUAAAAAF6kUHehJ8GnSdBUOOv6ujXLrWmsJRDCHgIQeAAAAAAAXqRR3QJbbz0hnQ8IvQ0fptGn+votneofTAAAAAAEBIKgb1wUAAAAAF6kU3k4ekGHKWRNbA1rV5tR5kEVDVNCHAQcXFgAUx4pFclNVgo1WWAdN1SYNX8tphTABCGsCRzBEAiB8Q+A6dep+Rz92vhy26lT0AjZn4PRLi8Bf9qoB/CMk0wIgP/Rj2PWZ3gEjUkTlhDRNAQ0gXwTO7t9n+V14pZ6oljUBIQMVmsAaoNWHVMS02LfTSe0e388LNitPa1UQZyOihY+FFgABABYAFEb2Giu6c4KO5YW0pfw3lGp9jMUUAAA=";
let body = original_psbt.as_bytes();
let headers = MockHeaders::new(body.len() as u64);
let proposal = UncheckedProposal {
v1: v1::UncheckedProposal::from_request(
body,
"maxadditionalfeecontribution=182&additionalfeeoutputindex=0",
headers,
)
.unwrap(),
context,
};
let p = proposal
.check_broadcast_suitability(None, |t| Err(Error::Server("mock error".into())));
assert_eq!(
p.err().unwrap().to_json(),
"{{ \"errorCode\": \"server-error\", \"message\": \"Internal server error\" }}"
); |
Fixed the payjoin-cli receive::error::Error handler and added a unit test |
9157070
to
4f8f952
Compare
Updated the last commit to use tACK 4f8f952 |
Recoverable errors are be shared with the Sender so that they might recover rather than necessarily waiting for the session to expire.
Only `Receiver.id()` needs to be public. Subdir can be a private pure function.
4f8f952
to
cdefa56
Compare
Ensure a request is produced from the v2 receiver state machine error extract function.
Whoops, 4f8f952 was based on an old base that had conflicts so I needed to rebase Wise switch to crate::receive::v1::test::proposal_from_test_vector() 🔥 |
Fix #468 with a simple approach: Just add the methods to UncheckedProposal which can be cloned at the beginning of the receive process.
This seems to be is the least invasive way to make this change that I didn't even think of in my enumerated approaches in #468.
Alternatively, we could have some way to extract an ErrorContext from which an Error (request,context) could be extracted from an
ErrorContext::extract_req(e: Error) -> (Request, ohttp_ctx)
But I think this gets us the progress we want and we can follow up if we decide that's a good idea with the rest of the receiver module error split.