* tutorial/receiving_messages: fix future output type bound
* tutorial/receiving_messages: remove unneeded message trimming
Trimming was done twice on messages, so one of the two instances can
be removed. I personally think removing the first instance, in which
we are splitting names from messages makes the code more readable
than removing the second instance, but other examples further in
the tutorial show the second instance removed.
* tutorial/receiving_messages: declare use of TcpStream and io::BufReader
Readers couldn't see the `use` lines corresponding to these two
structures.
* tutorial/connecting_readers_and_writers: typos and grammar fixes
* tutorial/all_together: remove unneeded use async_std::io
* tutorial: use SinkExt consistently from futures::sink::SinkExt
* tutorial/handling_disconnection: hide mpsc use clause and remove empty lines
The empty lines translate to the output making it look weird.
* tutorial/handling_disconnection: fix typos
* tutorial/handling_disconnection: use ? in broker_handle.await
We were happy to return an Err variant from the broker_handle before
and nothing has changed in this regard, so bubbling it up to run().
pull/561/head
Alejandro Martinez Ruiz5 years agocommitted byStjepan Glavina
So how do we make sure that messages read in `connection_loop` flow into the relevant `connection_writer_loop`?
So how do we make sure that messages read in `connection_loop` flow into the relevant `connection_writer_loop`?
We should somehow maintain an`peers: HashMap<String, Sender<String>>` map which allows a client to find destination channels.
We should somehow maintain a `peers: HashMap<String, Sender<String>>` map which allows a client to find destination channels.
However, this map would be a bit of shared mutable state, so we'll have to wrap an `RwLock` over it and answer tough questions of what should happen if the client joins at the same moment as it receives a message.
However, this map would be a bit of shared mutable state, so we'll have to wrap an `RwLock` over it and answer tough questions of what should happen if the client joins at the same moment as it receives a message.
One trick to make reasoning about state simpler comes from the actor model.
One trick to make reasoning about state simpler comes from the actor model.
We can create a dedicated broker tasks which owns the `peers` map and communicates with other tasks by channels.
We can create a dedicated broker task which owns the `peers` map and communicates with other tasks using channels.
By hiding `peers` inside such an "actor" task, we remove the need for mutxes and also make serialization point explicit.
By hiding `peers` inside such an "actor" task, we remove the need for mutexes and also make the serialization point explicit.
The order of events "Bob sends message to Alice" and "Alice joins" is determined by the order of the corresponding events in the broker's event queue.
The order of events "Bob sends message to Alice" and "Alice joins" is determined by the order of the corresponding events in the broker's event queue.
Another problem is that between the moment we detect disconnection in `connection_writer_loop` and the moment when we actually remove the peer from the `peers` map, new messages might be pushed into the peer's channel.
Another problem is that between the moment we detect disconnection in `connection_writer_loop` and the moment when we actually remove the peer from the `peers` map, new messages might be pushed into the peer's channel.
To not lose these messages completely, we'll return the messages channel back to the broker.
To not lose these messages completely, we'll return the messages channel back to the broker.
This also allows us to establish a useful invariant that the message channel strictly outlives the peer in the `peers` map, and makes the broker itself infailable.
This also allows us to establish a useful invariant that the message channel strictly outlives the peer in the `peers` map, and makes the broker itself infallible.