## 1. Project Overview & Quickstart (tokio-rs/console-api) # console-api Open-source repository tokio-rs/console-api ### Repository Details - **Repository:** [tokio-rs/console-api](https://github.com/tokio-rs/console-api) - **Primary Language:** Code *Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.* ## 2. Official Technical Reference & Guides (tokio-rs/website) ## File: README.md # Tokio Website The website for the Tokio project. Lives at https://tokio.rs. Besides containing the content for the website, it also includes crates containing the example code used in the tutorial. These crates can be compiled and run. * [hello-tokio](tutorial-code/hello-tokio/src/main.rs) * [spawning](tutorial-code/spawning/src/main.rs) * [shared-state](tutorial-code/shared-state/src/main.rs) * [channels](tutorial-code/channels/src/main.rs) * [io](tutorial-code/io) * [echo-server-copy](tutorial-code/io/src/echo-server-copy.rs) * [echo-server](tutorial-code/io/src/echo-server.rs) * [mini-tokio](tutorial-code/mini-tokio/src/main.rs) ## Contributing Thinking about contributing? Great! This should help you get the website running locally. ### Getting Started The website is built using [Next.js] paired with the [Bulma] CSS framework. You'll need NPM to install the required packages with: ```bash npm install ``` Next, start the development server: ```bash npm run dev ``` Then, open [http://localhost:3000](http://localhost:3000). [Next.js]: https://nextjs.org/ [Bulma]: https://bulma.io/ ### Resources To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - [Bulma documentation](https://bulma.io/documentation/) - learn about Bulma. ## License This project is licensed under the [MIT license](LICENSE). ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Tokio by you, shall be licensed as MIT, without any additional terms or conditions. You can run our tests by running the commands: ``` # in doc-test (unstable APIs are needed by some tests) RUSTFLAGS="--cfg tokio_unstable" cargo +nightly test # in tutorial-code cargo test --all ``` The doc tests verify that all code blocks are valid Rust, and the tutorial-code folder contains the full code examples from the tutorial. --- ## File: content/tokio/topics/bridging.md --- title: "Bridging with sync code" --- In most examples of using Tokio, we mark the main function with `#[tokio::main]` and make the entire project asynchronous. In some cases, you may need to run a small portion of synchronous code. For more information on that, see [`spawn_blocking`]. In other cases, it may be easier to structure the application as largely synchronous, with smaller or logically distinct asynchronous portions. For instance, a GUI application might want to run the GUI code on the main thread and run a Tokio runtime next to it on another thread. This page explains how you can isolate async/await to a small part of your project. # What `#[tokio::main]` expands to The `#[tokio::main]` macro is a macro that replaces your main function with a non-async main function that starts a runtime and then calls your code. For instance, this: ```rust #[tokio::main] async fn main() { println!("Hello world"); } ``` is turned into this: ```rust fn main() { tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap() .block_on(async { println!("Hello world"); }) } ``` by the macro. To use async/await in our own projects, we can do something similar where we leverage the [`block_on`] method to enter the asynchronous context where appropriate. # A synchronous interface to mini-redis In this section, we will go through how to build a synchronous interface to mini-redis by storing a `Runtime` object and using its `block_on` method. In the following sections, we will discuss some alternate approaches and when you should use each approach. The interface that we will be wrapping is the asynchronous [`Client`] type. It has several methods, and we will implement a blocking version of the following methods: * [`Client::get`] * [`Client::set`] * [`Client::set_expires`] * [`Client::publish`] * [`Client::subscribe`] To do this, we introduce a new file called `src/clients/blocking_client.rs` and initialize it with a wrapper struct around the async `Client` type: ```rs use tokio::net::ToSocketAddrs; use tokio::runtime::Runtime; pub use crate::clients::client::Message; /// Established connection with a Redis server. pub struct BlockingClient { /// The asynchronous `Client`. inner: crate::clients::Client, /// A `current_thread` runtime for executing operations on the /// asynchronous client in a blocking manner. rt: Runtime, } impl BlockingClient { pub fn connect(addr: T) -> crate::Result { let rt = tokio::runtime::Builder::new_current_thread() .enable_all() .build()?; // Call the asynchronous connect method using the runtime. let inner = rt.block_on(crate::clients::Client::connect(addr))?; Ok(BlockingClient { inner, rt }) } } ``` Here, we have included the constructor function as our first example of how to execute asynchronous methods in a non-async context. We do this using the [`block_on`] method on the Tokio [`Runtime`] type, which executes an asynchronous method and returns its result. One important detail is the use of the [`current_thread`] runtime. Usually when using Tokio, you would be using the default [`multi_thread`] runtime, which will spawn a bunch of background threads so it can efficiently run many things at the same time. For our use-case, we are only going to be doing one thing at the time, so we won't gain anything by running multiple threads. This makes the [`current_thread`] runtime a perfect fit as it doesn't spawn any threads. The [`enable_all`] call enables the IO and timer drivers on the Tokio runtime. If they are not enabled, the runtime is unable to perform IO or timers. > **warning** > Because the `current_thread` runtime does not spawn threads, it only operates > when `block_on` is called. Once `block_on` returns, all spawned tasks on that > runtime will freeze until you call `block_on` again. Use the `multi_threaded` > runtime if spawned tasks must keep running when not calling `block_on`. Once we have this struct, most of the methods are easy to implement: ```rs use bytes::Bytes; use std::time::Duration; impl BlockingClient { pub fn get(&mut self, key: &str) -> crate::Result