doc-push
doc-push copied to clipboard
Cookbook
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.
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
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?
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.
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.
@rrichardson sure, however you want to do it 👍
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.
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.
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.
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.
- Spawn a task to work in the background and check the results.
- Shutting down: monitor for signals, shutdown sockets, background tasks, and the reactor. Setting a timer for non-graceful override.
- Multiple tasks mutating a single Hash Map
- Enqueuing messages to be sent by another task.
- Launch a pool for CPU intensive tasks and check the results
- Send a file over a TcpStream
- Return different future/stream types from different branches in a function using Box
- Return different future/stream types from different branches using Either or similar.
- Handle multiple Event types from multiple stream types using type unification and select()
- Use DNS to resolve a host and then connect
- Read and write via stdin and stdout
- Spawn, Manage, and communicate with child processes.
- Send a TCP/UDP packet every 5 seconds.
- Listen and timeout on receiving a heartbeat over TCP/UDP
- Limit/kill a stream by duration (e.g 30 seconds)
- Limit/kill a stream by number of messages (e.g. using take)
- Handle errors in a stream using a transport decorator
@rrichardson very nice list
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.
A full example of DelayQueue with usage.
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.
Another example:
Download files using an HTTP client in parallel and write them to files.
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+ ?
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.