Tokio/Async design of pub/sub rest message fanout question

Hi all, I need a hint on how to continue
Want to write a little fanout server for rest messages with pub/sub semantic.
I have got my server setup with tide which is using hyper internally.
I want to continue using hyper to send out requests to registered subscribers.
Traditionally I would have 1 thread handling all the incoming traffic and 1 thread per subscriber polling on a queue(eg. crossbeam) and sending stuff until closed.
Now with tokio/async I am entering unknown territory.
My idea is to have a futures mpsc per subscriber.
So for each new message I will send it into the channel.
On the for_each of the channel I will send my requests out using hyper and use await! to wait for it to return from sending before sending the next one?
Now does the send to the channel already block the sender until the channel is done?
Will the await! in the future for_each of the receiver work at all?
Sorry about my confusion…

With mpsc the try_send function as described does not block. You have the choice of bound or unbound, bound can return a fail if the buffer is full.

Tokio is currently crate-futures01 while async/await is nightly std + crate-futures03 (i.e. futures-preview.) It will be messy for a while.
for_each you return a future if you want serial or spawn to have concurrent.
futures03 async code I have seen uses for serial something like

while Some(val) = await!(stream.next()) { await!(something(val)) }

You can think of tasks as lightweight threads. They are cheaper, can run in concurrently and will block (the task, not the thread) if you call await. You must be aware of that. It’s not always ok to block a task that handles many incoming messages until the backend has finished processing one message, otherwise you will no longer work concurrently. That can happen with the back pressure of a bounded channel.

It means that you can do concurrent processing without needing threads. It depends how many connections you have though and how much computation you need. Ideally I try to use local spawning so I don’t have to pay the 10x overhead of thread synchronization. If you can’t do that, it’s common to spawn tasks on a threadpool.

For combining async_await and tokio. I found it quite workable by sticking strictly to futures 0.3 myself and just using the compatibility layer whenever libraries give me futures or streams that are 0.1. You don’t need a tokio executor. Futures spawned on the futures 0.3 executor with compat() will still use their reactor to wake up the task for networking and other (m)IO.

There has also been work on 0.3 IO libs, but they’re definitely not as mature as tokio. See: Romio, Juliex, runtime. And they won’t work with tide.