Skip to content

Commit

Permalink
feat: Update helper docs
Browse files Browse the repository at this point in the history
  • Loading branch information
kdheepak committed Feb 20, 2024
1 parent aed1250 commit 7168bb6
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 29 deletions.
4 changes: 2 additions & 2 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ export default defineConfig({
{ label: "Crates TUI", link: "/tutorials/crates-tui/" },
{ label: "Main", link: "/tutorials/crates-tui/main" },
{
label: "crates_io_api Helper",
link: "/tutorials/crates-tui/crates_io_api_helper",
label: "Helper",
link: "/tutorials/crates-tui/crates-io-api-helper",
},
{ label: "Tui", link: "/tutorials/crates-tui/tui" },
{ label: "Errors", link: "/tutorials/crates-tui/errors" },
Expand Down
6 changes: 4 additions & 2 deletions code/crates-tui-tutorial-app/src/bin/part-helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,20 @@ async fn fetch_crates_and_metadata(
.await
// ANCHOR_END: crates_query
.map_err(|err| format!("API Client Error: {err:#?}"))?;
// ANCHOR: crates_response
let crates = page_result.crates;
// ANCHOR_END: crates_response
Ok(crates)
}

/// Handles the result after fetching crates and sending corresponding
/// actions.
fn update_state_with_fetched_crates(
crates: Vec<crates_io_api::Crate>,
params: &SearchParameters,
search_params: &SearchParameters,
) {
// ANCHOR: update_state
let mut app_crates = params.crates.lock().unwrap();
let mut app_crates = search_params.crates.lock().unwrap();
app_crates.clear();
app_crates.extend(crates);
// ANCHOR_END: update_state
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
---
title: Crates IO API
title: Crates IO API Helper
---

In this tutorial, we are going to use the `crates_io_api` crate's [`AsyncClient`] to retrieve
results from a search query to crates.io.
results from a search query to crates.io, and make a helper module to simplify handling of the
request and response for the purposes of the tutorial.

[`AsyncClient`]:
https://docs.rs/crates_io_api/latest/crates_io_api/struct.AsyncClient.html#method.new

In order to initialize the client, you have to provide an email as the user agent. In the source
code of this tutorial, we read this email from the environment variable
`CRATES_TUI_TUTORIAL_APP_MYEMAIL` at run time.
`CRATES_TUI_TUTORIAL_APP_MYEMAIL`.

```rust
let email = env!("CRATES_TUI_TUTORIAL_APP_MYEMAIL");
Expand All @@ -29,28 +30,33 @@ You can set up a environment variable for the current session by exporting a var
export [email protected]
```

Or just hardcode your email into your working copy.
Or just hardcode your email into your working copy of the source code

```rust
let email = "[email protected]";
```

:::

Once you have created a client, you can make a query using the [`crates`] function:
Once you have created a client, you can make a query using the [`AsyncClient::crates`] function:

[`crates`]: https://docs.rs/crates_io_api/latest/crates_io_api/struct.AsyncClient.html#method.crates
[`AsyncClient::crates`]:
https://docs.rs/crates_io_api/latest/crates_io_api/struct.AsyncClient.html#method.crates

```rust
{{#include @code/crates-tui-tutorial-app/src/crates_io_api_helper.rs:crates_query}}
```

This `crates` method takes a [`CratesQuery`] object that you need to construct.
This `crates` method takes a [`CratesQuery`] object that you will need to construct.

[`CratesQuery`]: https://docs.rs/crates_io_api/latest/crates_io_api/struct.CratesQuery.html

This `CratesQuery` object can be built with the following parameters

- Search query string
- Page number
- Page size
- Sort order
- Search query: `String`
- Page number: `u64`
- Page size: `u64`
- Sort order: `crates_io_api::Sort`

To make the code easier to manage, we'll store everything we need to construct a `CratesQuery` in a
`SearchParameters` struct:
Expand All @@ -68,8 +74,10 @@ pub struct SearchParameters {
}
```

A clone of `Arc<Mutex<Vec<crates_io_api::Crate>>>` will be passed into the `async` task within which
it will be populated with the results of the query after it is complete.
You'll notice that we also added a `crates` field to the `SearchParameters`. This `crates` field
will hold a clone of `Arc<Mutex<Vec<crates_io_api::Crate>>>` that will be passed into the `async`
task. Inside this `async` task it will be populated with the results of the query once the query is
completed.

You can construct the query using `crates_io_api`'s [`CratesQueryBuilder`]:

Expand All @@ -80,8 +88,14 @@ You can construct the query using `crates_io_api`'s [`CratesQueryBuilder`]:
{{#include @code/crates-tui-tutorial-app/src/bin/part-helper.rs:create_query}}
```

Once the request is completed, you can update the `Arc<Mutex<Vec<crates_io_api::Crate>>>` with the
response:
```rust
{{#include @code/crates-tui-tutorial-app/src/bin/part-helper.rs:crates_query}}

{{#include @code/crates-tui-tutorial-app/src/bin/part-helper.rs:crates_response}}
```

Once the request is completed, you can clear the existing results and update the
`Arc<Mutex<Vec<crates_io_api::Crate>>>` (i.e. the `search_params.crates` field) with the response:

```rust
{{#include @code/crates-tui-tutorial-app/src/bin/part-helper.rs:update_state}}
Expand Down
15 changes: 9 additions & 6 deletions src/content/docs/tutorials/crates-tui/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
title: Crates TUI
---

In the previous counter app, we had a purely sequential blocking application. There are times when
you may be interested in running IO operations or compute asynchronously.
In the previous counter app, we had a purely sequential blocking application. However, there are
times when you may be interested in running IO operations or computations asynchronously in between
rendering frames.

This tutorial will lead you through creating an async TUI app that lists crates from crates.io based
on a user search request in an `async` manner.
Expand Down Expand Up @@ -32,10 +33,6 @@ needed for writing network applications. We recommend you read the

Here's an example of all the dependencies in the `Cargo.toml` file required for this tutorial:

```toml
{{#include @code/crates-tui-tutorial-app/Cargo.toml:7:}}
```

Run the following to setup a new project:

```bash
Expand All @@ -53,3 +50,9 @@ This is what your folder structure should look like:
```

Let's go through making these files one by one, starting with `main.rs`.

```rust
{{#include @code/crates-tui-tutorial-app/src/bin/part-helper.rs:crates_query}}

{{#include @code/crates-tui-tutorial-app/src/bin/part-helper.rs:crates_response}}
```
15 changes: 11 additions & 4 deletions src/content/docs/tutorials/crates-tui/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ Sleeping for 5 seconds...
$
```

:::note[Homework]
:::tip

Use `time cargo run` to see how long a process takes to run.

:::

We recommend you experiment with `main` and `tokio` before moving forward.
:::note[Homework]

Hint: use `time cargo run` to see how long a process takes to run.
Experiment with `main` and `tokio` before moving forward.

For example, try to predicate what happens if you spawn multiple tokio tasks like so?

Expand All @@ -40,12 +44,15 @@ In the above example, if you change `#[tokio::main]` to `#[tokio::main(flavor =
can you predict what would happen? Run it to confirm. Do you understand why it behaves the way it
does?

Now, what happens if you run the following instead?
Now, what happens if you run the following with `#[tokio::main]` instead?

```rust
{{#include @code/crates-tui-tutorial-app/src/bin/part-main-tasks-sequential.rs}}
```

Do you understand the different between creating a future and `await`ing on it later versus spawning
a future and `await`ing on the `JoinHandle` later?

:::

<!--
Expand Down

0 comments on commit 7168bb6

Please sign in to comment.