Timeout - toy-rpc Book

# Set timeout for an RPC call

A default timeout of 10 seconds is assigned to client upon creation, and this default timeout can be changed using `set_default_timeout(duration: Duration)` method on the client. Each RPC call will have the default timeout unless it is prepended with `set_next_timeout(..)` method. The client can set the timeout for the next RPC request using the `set_next_timeout(duration: Duration)` method, which can be chained with the `call` method. Please note that the timeout is ONLY set for the immediate next RPC call, and all RPC calls do not have timeout if not explicitly set using the `timeout` method.

We will re-use the example service definition in the cancellation chapter. For you convenience, the service definition and server code are copied below.

File structure:

    ./src
    ├── /bin
    │   ├── server.rs
    │   ├── client.rs
    └── lib.rs

Add dependencies:

    [dependencies]
    tokio = { version = "1", features = ["rt-multi-thread", "macros", "time"] }
    toy-rpc = { version = "0.7.5", features = ["tokio_runtime", "server", "client"] }

Service definition and implementation placed in `src/lib.rs`:

    use std::time::Duration;
    use toy_rpc::macros::export_impl;
    use tokio::time;

    struct Example { }

    #[export_impl]
    impl Example {
        #[export_method]
        async fn finite_loop(&self, args: ()) -> Result<(), String> {
            for counter in 0..500 {
                time::sleep(Duration::from_millis(500)).await;
            }
        }

        #[export_method]
        async fn echo(&self, args: String) -> Result<String, String> {
            Ok(args)
        }
    }

Serve the RPC service with `src/bin/server.rs`.

    use std::sync::Arc;
    use toy_rpc::Server;
    use tokio::net::TcpListener;

    // assume the name of the crate is "example"
    // import service definition and implementation
    use example::Example;

    #[tokio::main]
    async fn main() {
        let addr = "127.0.0.1:23333";
        let ex = Arc::new(Example { });
        let server = Server::builder()
            .register(ex)
            .build()

        let listener = TcpListener::bind(addr).await.unwrap();
        server.accept(listener).await.unwrap();
    }

On the client side, let's call the `finite_loop` RPC function with a timeout of three seconds.

    use std::time::Duration;
    use tokio::time;
    use toy_rpc::client::{Client, Call};

    // assume the name of the crate is "example"
    // import service definitions and generated client stub functions
    use example::*;

    #[tokio::main]
    async fn main() {
        let client = Client::dial("127.0.0.1:23333").await
            .expect("Failed to connect to server");

        let call: Call<()> = client
            .set_next_timeout(Duration::from_secs(3))
            .example() // access `Example` service
            .finite_loop(()); // access `finite_loop` method
        let result = call.await; // This should give you `Err(Error::Timeout)`
    }