Skip to content

Commit

Permalink
Merge pull request #474 from cunarist/add-error-handling-snippets
Browse files Browse the repository at this point in the history
Add error handling snippets
  • Loading branch information
temeddix authored Oct 26, 2024
2 parents f270370 + a413e84 commit 839a584
Showing 1 changed file with 26 additions and 6 deletions.
32 changes: 26 additions & 6 deletions documentation/docs/error-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,42 @@ There are recommended practices for managing errors in real-world applications.

## 🌪️ No Panicking

We recommend that you _not_ write panicking code at all, since Rust has the idiomatic `Result<T, E>`. Additionally, Rust _cannot_ catch panics on the web platform (`wasm32-unknown-unknown`), which can cause callers to wait indefinitely.
We recommend that you _not_ write panicking code at all, since Rust has the idiomatic `Result<T, E>`. Additionally, Rust _cannot_ catch panics on the web platform (`wasm32-unknown-unknown`), which can cause callers to wait forever.

```rust title="Rust"
fn not_good() {
let option = get_option();
let value_a = option.unwrap(); // This code can panic
let result = get_result();
let value_b = result.expect("This code can panic");
}

fn good() -> Result<(), SomeError> {
let option = get_option();
let value_a = option?;
let result = get_result();
let value_b = result?;
}
```

As the Rust documentation states, [most errors aren't serious enough](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html) to require the program or task to stop entirely.

## 🌈 Flexible Error Type

To manage Rust errors effectively, using a flexible error type is beneficial.

Developing an app differs from creating a library, as an app may encounter a wide range of error situations. Declaring distinct error types for hundreds of potential failures can be overwhelming. Therefore, it is advisable to utilize a single, flexible error type.
Developing an app differs from creating a library, as an app may encounter a wide range of error situations. Declaring a distinct error type for each potential failure can be overwhelming, unless the error cases are simple enough.

You can define your own custom error type or simply use one from `crates.io`:
Therefore, it is advisable to utilize a single, flexible error type. You can define your own or simply use one from `crates.io`:

- [anyhow](https://crates.io/crates/anyhow)

```rust
use anyhow::Result;

fn get_cluster_info() -> Result<ClusterMap> {
// `anyhow::Error` can be created from any error type.
// By using the `?` operator, the conversion happens automatically.
let config = std::fs::read_to_string("cluster.json")?;
let map: ClusterMap = serde_json::from_str(&config)?;
Ok(map)
Expand Down Expand Up @@ -76,20 +96,20 @@ async fn make_http_request() -> Result<MyResponse> {
// It can be any kind of failable function.
}

async fn do_work() -> Result<()> {
async fn top_level() -> Result<()> {
let my_response = make_http_request().await?;
// Do something with `my_response`.
// Additional processing may be written here.
Ok(())
}

async fn main_task() {
let result = do_work().await;
let result = top_level().await;
result.report();
}
```

This is how to use a top-level async function to report the propagated error. You will almost always use the `.report()` method because Rust automatically warns you about unused `Result`s.
This is how to use a top-level function to report the propagated error. You will almost always use the `.report()` method because Rust automatically warns you about unused `Result`s.

## 🧾 Logging

Expand Down

0 comments on commit 839a584

Please sign in to comment.