Skip to content
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

Merged
merged 17 commits into from
Jan 6, 2020

Conversation

jtgeibel
Copy link
Member

@jtgeibel jtgeibel commented Dec 21, 2019

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, 😓).

r? @smarnach

@smarnach
Copy link
Contributor

I plan to review this on 27 December, but this plan is subject to change…

@bors
Copy link
Contributor

bors commented Dec 23, 2019

☔ The latest upstream changes (presumably #1931) made this pull request unmergeable. Please resolve the merge conflicts.

@jtgeibel jtgeibel force-pushed the error-refactor-step3 branch from bfc1631 to ba52dff Compare December 26, 2019 23:07
@smarnach
Copy link
Contributor

I'm sorry I did not get to this today, and I won't have time until 2020-01-05.

@bors
Copy link
Contributor

bors commented Jan 4, 2020

☔ The latest upstream changes (presumably #2072) made this pull request unmergeable. Please resolve the merge conflicts.

@jtgeibel
Copy link
Member Author

jtgeibel commented Jan 4, 2020

I'm sorry I did not get to this today, and I won't have time until 2020-01-05.

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!

@jtgeibel jtgeibel force-pushed the error-refactor-step3 branch from ba52dff to 6f33bbe Compare January 4, 2020 17:46
@bors
Copy link
Contributor

bors commented Jan 5, 2020

☔ The latest upstream changes (presumably #2066) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Contributor

@smarnach smarnach left a 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.

src/background_jobs.rs Outdated Show resolved Hide resolved
src/bin/enqueue-job.rs Show resolved Hide resolved
@jtgeibel jtgeibel force-pushed the error-refactor-step3 branch from c621f0d to 541f710 Compare January 6, 2020 02:21
@jtgeibel
Copy link
Member Author

jtgeibel commented Jan 6, 2020

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.

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+

@bors
Copy link
Contributor

bors commented Jan 6, 2020

📌 Commit 541f710 has been approved by jtgeibel

@bors
Copy link
Contributor

bors commented Jan 6, 2020

⌛ Testing commit 541f710 with merge a251368...

bors added a commit that referenced this pull request Jan 6, 2020
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
@bors
Copy link
Contributor

bors commented Jan 6, 2020

☀️ Test successful - checks-travis
Approved by: jtgeibel
Pushing a251368 to master...

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.

4 participants