-
Notifications
You must be signed in to change notification settings - Fork 611
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
Add a concrete util::Error
type (step 3 of refactoring)
#2032
Conversation
I plan to review this on 27 December, but this plan is subject to change… |
☔ The latest upstream changes (presumably #1931) made this pull request unmergeable. Please resolve the merge conflicts. |
bfc1631
to
ba52dff
Compare
I'm sorry I did not get to this today, and I won't have time until 2020-01-05. |
☔ The latest upstream changes (presumably #2072) made this pull request unmergeable. Please resolve the merge conflicts. |
No problem at all. When you have a chance, would you start with PR #2071. It's a small fix and I'd like to get it deployed, just want a 2nd set of eyes on it. Thanks! |
ba52dff
to
6f33bbe
Compare
☔ The latest upstream changes (presumably #2066) made this pull request unmergeable. Please resolve the merge conflicts. |
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.
Phew, this one took me a while to get through. :)
I'm really glad you untangled this mess. The old code more or less threw away concrete error information in most cases and converted everything into a CargoError
, essentially introducing all the downsides of exceptions in languages like Python. The new version makes much better use of Rust's great error handling capabilities and has fewer explicit error conversions, dynamic calls and allocations.
And I couldn't find anything to complain about. :) On a high level, I completely agree with these changes, and in the details the compiler already did most of the review work for me.
It would be great if you could introduce some high-level documentation in a doc comment at the beginning of error.rs
, explaining the use cases for the main error or result types – basically a summary of what you put in the PR description. This could help keeping things nice and clean in the future (though the types in the preludes of the different subcomponents also help a lot ensuring future consistency).
I added a question or two, so I'm not going to r+ right now. However, feel free to merge without changes.
Background jobs do not need the JSON response functionality of `AppError`. Git operations, and most upload functions now use a generic boxed error.
c621f0d
to
541f710
Compare
I had been holding off on adding high-level documentation until things settled down, but I think this is now a good time to add these recommendations as documentation. (Especially since "I'll add some docs in a future PR" always takes longer than expected to get back around to.) I've rebased the PR, and added a commit adapting part of the PR description into module docs. Thanks for the review and feedback! @bors r+ |
📌 Commit 541f710 has been approved by |
Add a concrete `util::Error` type (step 3 of refactoring) This PR may be easier to review commit by commit. Overall this series continues the previous refactoring work in #1920 and #1929. In particular, a concrete `util::Error` error type is introduced. The code is updated to follow a style where: * The new concrete type `util::Error` is great for code that is not part of the request/response lifecycle. Binaries have been converted to `fn main() -> Result<(), Error>` where applicable. This avoids pulling in the unnecessary infrastructure to convert errors into a user facing JSON responses (relative to `AppError`). * There are now 13 results across 6 files for `, Error>`. Usage occurs in `src/bin/`, `src/boot/`, and `src/uploaders.rs`. * `diesel::QueryResult` - There is a lot of code that only deals with query errors. If only one type of error is possible in a function, using that specific error is preferable to the more general `util::Error`. This is especially common in model code. * There are now 49 results across 16 files for `QueryResult<`. Most usage is in `src/models/`, with some usage in `src/publish_rate_limit.rs`, `src/tasks/`, and `src/tests/`. * `util::errors::AppResult` - Some failures should be converted into user facing JSON responses. This error type is more dynamic and is box allocated. Low-level errors are typically not converted to user facing errors and most usage is within the models, controllers, and middleware layers (85 of 102 results below). * There are now 102 results across 36 files for `AppResult<`. Most usage is in `src/controllers/` and `src/models/`, with additional usage in `src/middleware/`, `src/{email,github,publish_rate_limit,router,uploaders}.rs`, and `src/{tests,util}/`. Finally, a `middleware::Result` type is introduced for use in middleware and router code. The behavior of `dyn AppError` and `chain_error` is a remaining area for improvement. There may be cases where we want to wrap an `internal` error in a user facing error (like `cargo_err` or `server_err`) and still have the internal error make it up to the logging middleware. However, I don't see an easy way to propagate this up the middleware stack (without encoding it in an internal response header that we later remove, :sweat:). r? @smarnach
☀️ Test successful - checks-travis |
This PR may be easier to review commit by commit. Overall this series continues the previous refactoring work in #1920 and #1929. In particular, a concrete
util::Error
error type is introduced. The code is updated to follow a style where:util::Error
is great for code that is not part of the request/response lifecycle. Binaries have been converted tofn main() -> Result<(), Error>
where applicable. This avoids pulling in the unnecessary infrastructure to convert errors into a user facing JSON responses (relative toAppError
)., Error>
. Usage occurs insrc/bin/
,src/boot/
, andsrc/uploaders.rs
.diesel::QueryResult
- There is a lot of code that only deals with query errors. If only one type of error is possible in a function, using that specific error is preferable to the more generalutil::Error
. This is especially common in model code.QueryResult<
. Most usage is insrc/models/
, with some usage insrc/publish_rate_limit.rs
,src/tasks/
, andsrc/tests/
.util::errors::AppResult
- Some failures should be converted into user facing JSON responses. This error type is more dynamic and is box allocated. Low-level errors are typically not converted to user facing errors and most usage is within the models, controllers, and middleware layers (85 of 102 results below).AppResult<
. Most usage is insrc/controllers/
andsrc/models/
, with additional usage insrc/middleware/
,src/{email,github,publish_rate_limit,router,uploaders}.rs
, andsrc/{tests,util}/
.Finally, a
middleware::Result
type is introduced for use in middleware and router code.The behavior of
dyn AppError
andchain_error
is a remaining area for improvement. There may be cases where we want to wrap aninternal
error in a user facing error (likecargo_err
orserver_err
) and still have the internal error make it up to the logging middleware. However, I don't see an easy way to propagate this up the middleware stack (without encoding it in an internal response header that we later remove, 😓).r? @smarnach