-
Notifications
You must be signed in to change notification settings - Fork 924
feat(object_store): publicly expose client error #6158
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
Conversation
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.
Thanks @kyle-mccarthy 🙏
It seems like that since the errors are now public the CI demands some of the methods be documented: https://github.com/apache/arrow-rs/actions/runs/10167031274/job/28118484246?pr=6158
@alamb I noticed that the main error variant suppresses this warning via Also, I have a branch that adds a |
Is there a reason not to document them? For example would they add no value over the names of the variants themselves? In my simple mind more documentation is always better than less (though I realize not everyone agrees with this assesment). |
a2c8c3d
to
3a04753
Compare
7216d16
to
e796cf1
Compare
Resolves linter warning about dead code when only default features are enabled.
@alamb Not at all, I added comments to the error enum! Note that I restricted the visibility of the |
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.
Looks good to me -- thank you @kyle-mccarthy
@@ -30,21 +30,32 @@ use tracing::info; | |||
/// Retry request error | |||
#[derive(Debug, Snafu)] | |||
pub enum Error { | |||
/// The response sent by the cloud provider was a redirect without a |
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.
If we do this I think we should make the variants opaque, and expose information with accessors. Otherwise it is going to be very hard to evolve this without introducing breaking changes
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 think keeping the underlying error opaque is pretty hard to use and clearly there appears to be a need to get finer grained information about what the error was
Otherwise it is going to be very hard to evolve this without introducing breaking changes
Perhaps another possibility is to mark it as [#non_exhaustive]
https://doc.rust-lang.org/reference/attributes/type_system.html
If we do this I think we should make the variants opaque, and expose information with accessors.
Are you suggesting something like
impl Error {
fn is_redirect(&self) -> bool {..}
fn status_code(&self) -> Option<StatusCode> {..}
...
}
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.
Are you suggesting something like
Yes, this is also what the underlying HTTP clients do as well. My aprehension is we're exposing a fair amount of internal details around how we perform requests, retries, etc... that seems undesirable.
non-exhaustive would help for adding new variants, but we'd be unable to change existing. If say we wanted to add more context to a retry error message, this would be a breaking change
I'm rather apprehensive about this as it exposes a fair bit of internal implementation details. Perhaps we could take a step back and address the motivating use-case, as then we can potentially develop a more targeted solution? The original ticket was centered on permission denied errors, and the proposal was to add a variant to represent this, is this the same request or something different? |
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.
cc @crepererum and @thinkharderdev for your thoughts
@@ -30,21 +30,32 @@ use tracing::info; | |||
/// Retry request error | |||
#[derive(Debug, Snafu)] | |||
pub enum Error { | |||
/// The response sent by the cloud provider was a redirect without a |
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 think keeping the underlying error opaque is pretty hard to use and clearly there appears to be a need to get finer grained information about what the error was
Otherwise it is going to be very hard to evolve this without introducing breaking changes
Perhaps another possibility is to mark it as [#non_exhaustive]
https://doc.rust-lang.org/reference/attributes/type_system.html
If we do this I think we should make the variants opaque, and expose information with accessors.
Are you suggesting something like
impl Error {
fn is_redirect(&self) -> bool {..}
fn status_code(&self) -> Option<StatusCode> {..}
...
}
If someone has time to design a better error abstraction for the client I would be happy to try and review it. However, I don't think I would likely have the time do to so however |
My personal feeling is the better abstraction is to add a permission denied variant to the top-level error, as originally stated on the ticket. This will work across all stores, is easily discoverable and easy to understand. The problem is for historical reasons this isn't marked non-exhaustive and so adding this would be a breaking change. So either we defer this to the next breaking release, or we do something in the middleground to expose this variant in a non-breaking fashion. One stopgap option could simply be to add an opaque PermissionError that the generic error can be downcast to. It all really depends on what the use-case is and how acute the need is |
@tustvold I understand your concerns and feel like they are valid. I have a branch that takes an alternative approach and surfaces permission problems though a I am primarily wanting to be able able to identify permission related problems, so either direction would help me. However, I think the core problem would still exist if just the |
Right, the alternative being we expose public types and those types then become part of the public API, but in a somewhat obfuscated manner. This gets particularly spicy if one exposes foreign types, which we probably do in some places, then not only are these crates part of your public API but if those crate's make a breaking release any error handling code will happily build against a different version, and just silently not work 😄 The approach as it stands is to have explicit semantic error categories, this gives a lot of freedom to make changes to the implementations, and has a lot of precedent in the ecosystem (e.g. hyper, reqwest) and the standard library (std::io::Error), but does come with downsides should a particular semantic category be omitted. Edit: I've created #6165 as I think it is something we should do anyway |
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 PR kinda sidesteps / ignores the discussion in #5345 that -- more or less -- concluded that we do NOT want to expose too many implementation details.
So what is the path forward here? Users continue to parse the text of the error messages if they need more detail on what error occured? Someone (who?) creates a more detailed error categorization? Something else? |
This, by whoever steps up and does the work. |
Closing this in favor of #6194. |
Which issue does this PR close?
Closes #5345.
Rationale for this change
Exposing the client error publicly allows accessing the status code of the response associated with the error. This gives the user more control over error handling, such as special handling for authn/authz errors.
What changes are included in this PR?
expose
client::Error as ClientError
Are there any user-facing changes?
Yes
Notes
PermissionDenied
variant could be added tocrate::Error
.source
could be changed toreqwest::Error
when the client error is converted tocrate::Error
. (Would allow downcasting directly to reqwest::Error.)