Improve receive error heirarchy#1031
Conversation
The only non-implmementation variant is in fact an error arising from the implmentation. Therefore, remove that variant and all of the propagation code resulting from it.
It's infallible.
The private functions just return an InternalPayloadError. This is a step toward separate reply error behavior for v1/v2.
| { | ||
| Ok(inner) => inner, | ||
| Err(e) => { | ||
| // FIXME: follow up by returning a terminal error rather than replyable error |
There was a problem hiding this comment.
this is intentionally left in to be fixed when SessionInvalid is swapped for more specific classification.
Pull Request Test Coverage Report for Build 17412954810Details
💛 - Coveralls |
spacebear21
left a comment
There was a problem hiding this comment.
Concept ACK - The Protocol v. Implementation error distinction is way more meaningful than ReplyToSender v. V2.
In V1, that means serializing the error as JSON and making the network call to respond as well as printing a log message. That's demonstrated here in the 5th commit. We'll need to introduce some testing around this as it firms up
I think introducing a basic test for this would fix the failing cargo-mutants check in CI.
I think all error states, fatal or transient, need to be persisted in v2+ that way on replay a client can be presented with the error as the current state, even if transient. Fatal errors may need to be replayed and marked as to whether or not they have been communicated to the counterparty or if further action is required at a later resumption.
This sounds right to me.
payjoin-ffi/src/receive/error.rs
Outdated
| /// Errors that can be replied to the sender | ||
| #[error("Replyable error: {0}")] |
There was a problem hiding this comment.
Error string and docstring need update too
payjoin/src/core/receive/error.rs
Outdated
| @@ -9,32 +9,40 @@ use crate::error_codes::ErrorCode::{ | |||
| #[non_exhaustive] | |||
| pub enum Error { | |||
| /// Errors that can be replied to the sender | |||
| /// after conversion into [`JsonReply`] | ||
| #[derive(Debug)] | ||
| pub enum ReplyableError { | ||
| pub enum ProtocolError { |
There was a problem hiding this comment.
The docstring for this enum too
| V1(e) => e.into(), | ||
| Implementation(_) => JsonReply::new(Unavailable, "Receiver error"), | ||
| #[cfg(feature = "v2")] | ||
| V2(_) => JsonReply::new(Unavailable, "Receiver error"), |
There was a problem hiding this comment.
We may want to implement impl From<&SessionError> for JsonReply even if all variants are handled in the same way (this is currently the case for v1::RequestError)
There was a problem hiding this comment.
Because such From impl is part of the public api, I figured this one liner was a simpler solution. Are yo opposed to handling RequestError that way instead here too, in contrast to your suggestion?
There was a problem hiding this comment.
Handling RequestError here instead sounds good
Before we were just responding with Display strings instead of the correct JSON error payload. Add a `JsonReply::status_code` function to report the status code also.
And v2 to re-named ProtocolError
3bc42dd to
59dad2e
Compare
| if expected_ntxid != actual_ntxid { | ||
| return Err(FinalizeProposalError::NtxidMismatch(expected_ntxid, actual_ntxid)); | ||
| return Err(ImplementationError::from( | ||
| format!("Ntxid mismatch: expected {expected_ntxid}, got {actual_ntxid}").as_str(), |
There was a problem hiding this comment.
I realize this is just a code move, but I wonder if we should be more descriptive about why this error occurs e.g. "this is not the expected Payjoin transaction"
spacebear21
left a comment
There was a problem hiding this comment.
code ACK 59dad2e, I can re-ACK if you want to address my newer comments, or they can be handled in a follow-up.
I delete a few error types, refine function definitions, and ultimately change the
receivemodule error heirarchy so that the top levelreceive::Erroris the only one that contains theImplementationvariant, where previously these could be defined in multiple places across the stack.In order to solve #793 and #403 two (currently conflated) problems must be solved: Error Handling and error classification. This addresses the latter.
I'll need to follow this up to address #793, but getting the hierarchy of classification right, including the removal of superfluous errors was my first step.
Error handling involves a response to the counterparty and reporting to the client. In V1, that means serializing the error as JSON and making the network call to respond as well as printing a log message. That's demonstrated here in the 5th commit. We'll need to introduce some testing around this as it firms up. In v2, errors need to be persisted. They can be either fatal or transient in nature, with basically all errors being Implementation errors. It is not yet clear to me whether all ImplementationError types imply transient errors for certain, but for now that is how we make the distinction. if this is not the case, we must come up with some enumeration for ImplementationErrors that let us better categorize them so that the history replay can handle them appropriately.
Implementation Error classification
For example, this was an LLM generated suggestion of such classification:I think all error states, fatal or transient, need to be persisted in v2+ that way on replay a client can be presented with the error as the current state, even if transient. Fatal errors may need to be replayed and marked as to whether or not they have been communicated to the counterparty or if further action is required at a later resumption. In order to serialize these errors I believe we want to expand on the
ErrorCodetype to be aSerializableErrorthat includes the error kind with fixed messages for presentation. Perhaps more details may be logged at the time of conversion.In order to replay them I think we need to replace the
SessionEvent::SessionInvalidvariant withTransientandFatalvariants that just hold thisSerializableErrorinstead of the current TODO marked typeSessionInvalid(String, Option<JsonReply>),Pull Request Checklist
Please confirm the following before requesting review:
AI
in the body of this PR.