tokio-rs / doc-push

Tokio doc blitz effort - A concerted effort to improve Tokio's documentation.
MIT License
50 stars 7 forks source link

Cookbook #23

Open carllerche opened 5 years ago

carllerche commented 5 years ago

What kinds of things should be in the cookbook?

Prior discussion

eminence commented 5 years ago

How do I hook up timers to the networking stack? For example, how do I send a UDP packet every 5 seconds?

Getting a a timer set-up is really easy:

    let interval = Interval::new_interval(Duration::from_secs(5));

    let task = interval.map_err(|e| ()).for_each(|_| {
        println!("Timer has fired");
        future::done(Ok(()))
    });

    tokio::run(task);

Sending a single message on a socket is pretty easy, too

    let local = "0.0.0.0:12345".parse().unwrap();
    let target = "10.11.12.13:12345".parse().unwrap();

    let socket = UdpSocket::bind(&local).unwrap();

    let task = socket.send_dgram("hello".as_bytes(), &target).then(|r| {
        if let Ok(s) = r {
            println!("Successfully send bytes to socket");
        // could send another message using `s` now if we wanted
        } else {
            println!("Failed to send bytes");
        }
        future::done(Ok(()))
    });

    tokio::run(task);

But how do I combine them? The hard part seems to be that send_dgram takes ownership of the socket for a little while, which prevents the socket from being owned by the for-each closure.

eminence commented 5 years ago

What's the pattern for taking "events" from multiple sources and handling them all in the same handler? For example, waiting for network data, waiting for keyboard input, and a timer?

My guess is that you would take your streams and map them all to the same wrapper type (probably an enum), and then use Stream::select to merge them all into a single Stream

carllerche commented 5 years ago

Ok, I seeded the cookbook outline here.

Please provide additional items via PR 👍

eminence commented 5 years ago

Could you please add another small seed that shows the structure for providing actual cookbook entries? (I mean the actual example code, not just the description of the cookbook entry). Should we just create new .md files in a new cookbook/ sub-directory?

carllerche commented 5 years ago

I would probably follow the structure of https://rust-lang-nursery.github.io/rust-cookbook/.

A new folder for cookbook and one md file per category with all the examples for that category on the same page.

If you are trying to get started and creating the structure is not something you want to do in the PR, just post a gist here and I can use that to setup the structure.

rrichardson commented 5 years ago

If we could organize a group effort in the Tokio channels, I bet we could get spans of code from dozens of existing projects that demonstrate these tasks.

carllerche commented 5 years ago

@rrichardson sure, however you want to do it 👍

ghost commented 5 years ago

A topic that I'm interested in is client connection pooling.

I've been thinking about toying around with the Cassandra database protocol that communicates over TCP and supports asynchronous connections. There can be multiple connections to multiple DB servers and each connection can be used to send multiple requests (each request is assigned a stream ID that will also be added to the response, so that the driver knows what query to complete). Maybe a high level concept of that description could be implemented?

That would be a pretty involved example and maybe it's not suitable for this cookbook, but I just thought I'd spit it out here.

carllerche commented 5 years ago

A connection pool is definitely a good example... I wonder if it should be included as a dedicated page in the Transports section.

Also, maybe the cookbook should link to examples throughout the guide as well in cases where the example is more complex.

ghost commented 5 years ago

The connection pool example would be a great addition to the transports section as it shows how to implement a more complex client protocol implementation. Then the transports section has both client and server protocol implementation examples covered. IMO it's also refreshing to see stuff besides HTTP.

rrichardson commented 5 years ago

Below is a wish-list that I've distilled from https://github.com/tokio-rs/doc-push/blob/master/outline/cookbook.md for quick reference. I'll update it with source/gist links as we find them.

  1. Spawn a task to work in the background and check the results.
  2. Shutting down: monitor for signals, shutdown sockets, background tasks, and the reactor. Setting a timer for non-graceful override.
  3. Multiple tasks mutating a single Hash Map
  4. Enqueuing messages to be sent by another task.
  5. Launch a pool for CPU intensive tasks and check the results
  6. Send a file over a TcpStream
  7. Return different future/stream types from different branches in a function using Box
  8. Return different future/stream types from different branches using Either or similar.
  9. Handle multiple Event types from multiple stream types using type unification and select()
  10. Use DNS to resolve a host and then connect
  11. Read and write via stdin and stdout
  12. Spawn, Manage, and communicate with child processes.
  13. Send a TCP/UDP packet every 5 seconds.
  14. Listen and timeout on receiving a heartbeat over TCP/UDP
  15. Limit/kill a stream by duration (e.g 30 seconds)
  16. Limit/kill a stream by number of messages (e.g. using take)
  17. Handle errors in a stream using a transport decorator
carllerche commented 5 years ago

@rrichardson very nice list

leshow commented 5 years ago

A fairly simple one, but something I ran into: spawning tasks on the current thread only (without using the default runtime), lending handle references to spawn tasks on the same thread.

jgrund commented 5 years ago

A full example of DelayQueue with usage.

kosta commented 5 years ago

I would like cookbook recipe for limiting the number of in-flight requests.

E.g. when I'm feeding a channel from a separate thread that is read from tokio as a Stream; and only want n Futures to be in-flight at a time. Desired behaviour would be that limiting reading from the stream would put backpressure on the "feeding" thread.

carllerche commented 5 years ago

Another example:

Download files using an HTTP client in parallel and write them to files.

rrichardson commented 5 years ago

Download files using an HTTP client in parallel and write them to files.

I just wrote this exact thing for work. I could probably sanitize it and throw it in.

On a side note: What is the scope of this cookbook now? Async/Await and Tokio v0.2+ ?

carllerche commented 5 years ago

Yes, async/await and 0.2 :) I am hoping to get this done around the time the final lands... 3 months maybe, 6 months definitely.