This commit is contained in:
Daniel Flanagan 2022-02-15 10:06:37 -06:00
parent 91cc3a62e4
commit 5767017fed
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4

View file

@ -18,7 +18,7 @@ alias RanchTalk.TalkTimer
%{ %{
# 10 minutes # 10 minutes
seconds_to_count: 60 * 10, seconds_to_count: 60 * 10,
done_message: "Time's up! Shut up and get back to work!" done_message: "Time's up! Shut up and get back to work! 💩"
} }
|> TalkTimer.new() |> TalkTimer.new()
|> TalkTimer.start() |> TalkTimer.start()
@ -71,7 +71,7 @@ loop look _very loosely_ like this now:
1. Open a socket 1. Open a socket
2. Check if any pending connections exist on the socket 2. Check if any pending connections exist on the socket
3. If there are any pending connections, add them to our list of connections 3. If there are any pending connections, add them to our list of connections
* This is that "acceptor" part that Ranch takes care of for us - This is that "acceptor" part that Ranch takes care of for us
4. For each active connection, check if the connection has any messages 4. For each active connection, check if the connection has any messages
5. If the connection has any messages, handle them 5. If the connection has any messages, handle them
6. For each active connection, check if the connection is still active 6. For each active connection, check if the connection is still active
@ -140,33 +140,33 @@ documentation to see how it works so we know better what to look for. Don't
worry, I'm not really going to make you read documentation yourself during worry, I'm not really going to make you read documentation yourself during
a talk, so I've summarized the important stuff we'll look at below: a talk, so I've summarized the important stuff we'll look at below:
* https://ninenines.eu/docs/en/ranch/2.1/guide/introduction/ - https://ninenines.eu/docs/en/ranch/2.1/guide/introduction/
* Just the stuff we've already talked about (minus all the boring socket - Just the stuff we've already talked about (minus all the boring socket
detail stuff) detail stuff)
* https://ninenines.eu/docs/en/ranch/2.1/guide/listeners/ - https://ninenines.eu/docs/en/ranch/2.1/guide/listeners/
* We start Ranch by adding the dependency and running - We start Ranch by adding the dependency and running
[`:application.ensure_all_started(:ranch)`](https://ninenines.eu/docs/en/ranch/2.1/manual/) [`:application.ensure_all_started(:ranch)`](https://ninenines.eu/docs/en/ranch/2.1/manual/)
* We can start a listener with - We can start a listener with
[`:ranch.start_listener/5`](https://ninenines.eu/docs/en/ranch/2.1/manual/ranch.start_listener/) [`:ranch.start_listener/5`](https://ninenines.eu/docs/en/ranch/2.1/manual/ranch.start_listener/)
* https://ninenines.eu/docs/en/ranch/2.1/guide/internals/ - https://ninenines.eu/docs/en/ranch/2.1/guide/internals/
* Ranch is an OTP `Application` (named `:ranch`) - Ranch is an OTP `Application` (named `:ranch`)
* It has a "top `Supervisor`" which supervises the `:ranch_server` process - It has a "top `Supervisor`" which supervises the `:ranch_server` process
_and_ any listeners _and_ any listeners
* Ranch uses a "custom `Supervisor`" for managing connections - Ranch uses a "custom `Supervisor`" for managing connections
* Listeners are grouped into the `:ranch_listener_sup` `Supervisor` - Listeners are grouped into the `:ranch_listener_sup` `Supervisor`
* Listeners consist of three kinds of processes: - Listeners consist of three kinds of processes:
* The listener `GenServer` - The listener `GenServer`
* A `Supervisor` that watches the acceptor processes - A `Supervisor` that watches the acceptor processes
* The second argument to `:ranch/start_listener/5` indicates the number - The second argument to `:ranch/start_listener/5` indicates the number
of processes that will be accepting new connections and we should be of processes that will be accepting new connections and we should be
careful choosing this number careful choosing this number
* It defaults to `100` - It defaults to `100`
* A `Supervisor` that watches the connection processes - A `Supervisor` that watches the connection processes
* Each listener is registered with the `:ranch_server` `GenServer` - Each listener is registered with the `:ranch_server` `GenServer`
* All socket operations go through "transport handlers" - All socket operations go through "transport handlers"
* These are simple callback modules (`@behaviour`s) for performing - These are simple callback modules (`@behaviour`s) for performing
operations on sockets operations on sockets
* Accepted connections are given to "the protocol handler" (just TCP for our - Accepted connections are given to "the protocol handler" (just TCP for our
use case) use case)
Sweet! Armed with this knowledge, we should be able to find evidence of these Sweet! Armed with this knowledge, we should be able to find evidence of these
@ -198,10 +198,10 @@ Now, if you selected the Livebook node and NOT the empty shell-of-a-node that
is the attached Mix project (you should switch to the correct one now!), you is the attached Mix project (you should switch to the correct one now!), you
will see that `:ranch_server` monitors a couple of `Supervisor`s: will see that `:ranch_server` monitors a couple of `Supervisor`s:
* `:ranch_conns_sup` - `:ranch_conns_sup`
* `:ranch_listener_sup` - `:ranch_listener_sup`
* `:ranch_conns_sup` - `:ranch_conns_sup`
* `:ranch_listener_sup` - `:ranch_listener_sup`
Awesome! We can see the connection `Supervisor` and listener `Supervisor` for Awesome! We can see the connection `Supervisor` and listener `Supervisor` for
port `5588` and likewise for port `5589`. The former for serving the page port `5588` and likewise for port `5589`. The former for serving the page
@ -216,8 +216,7 @@ processes under `Monitors` hanging out waiting for connections. What gives?
Yeah, I dunno. Maybe somebody in the audience knows why they aren't monitored Yeah, I dunno. Maybe somebody in the audience knows why they aren't monitored
(or at least why they don't show up here). (or at least why they don't show up here).
But if you go to [the Processes page](/dashboard/processes) and `Ctrl-F But if you go to [the Processes page](/dashboard/processes) and `Ctrl-F ":ranch_acceptor.loop"` you will see exactly 200 results.
":ranch_acceptor.loop"` you will see exactly 200 results.
Ok, this is cool and all, and if we had time, we could look at this in the Ok, this is cool and all, and if we had time, we could look at this in the
Observer from pretty much any `iex` session like so: Observer from pretty much any `iex` session like so:
@ -280,13 +279,15 @@ to it and see if it really does echo back to us! You can use `nc` (netcat),
`telnet`, or we can use Erlang's `:gen_tcp` like so: `telnet`, or we can use Erlang's `:gen_tcp` like so:
```elixir ```elixir
{:ok, socket} = :gen_tcp.connect({127, 0, 0, 1}, 5555, [:binary]) {:ok, socket} = :gen_tcp.connect({127, 0, 0, 1}, 5555, [:binary, active: true])
``` ```
See how `:gen_tcp` returns `{:ok, #Port<...>}`? A `Port` is a special See how `:gen_tcp` returns `{:ok, #Port<...>}`? A `Port` is a special
Erlang/OTP-ism we can learn about another time. For now, should have got us Erlang/OTP-ism we can learn about another time. For now, should have got us
a connection! Let's send something. a connection! Let's send something.
**NOTE**: If you don't hurry and send the message, the TCP socket will be closed due to your inactivity. Better act fast!
```elixir ```elixir
:gen_tcp.send(socket, "Hello, socket! " <> to_string(DateTime.utc_now())) :gen_tcp.send(socket, "Hello, socket! " <> to_string(DateTime.utc_now()))
``` ```
@ -295,8 +296,7 @@ And if we got `:ok`, this `Process` should have a message in its
[mailbox](https://elixir-lang.org/getting-started/processes.html). [mailbox](https://elixir-lang.org/getting-started/processes.html).
```elixir ```elixir
messages = :erlang.process_info(self(), :messages) :erlang.process_info(self(), :messages)
IO.inspect(messages)
``` ```
So it works. You get it now. So it works. You get it now.