You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: lib/elixir/pages/mix-and-otp/config-and-distribution.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,7 @@ Let's do this.
13
13
14
14
## Application environment
15
15
16
-
In the chapter [Registries, applications, and supervisors](supervisor-and-application.md), we have learned that our project is backed by an application, which bundles our modules and specifies how your supervision starts and shuts down. Each application can also have its own configuration, which in Erlang/OTP (and therefore Elixir) is called "application environment".
16
+
In the chapter [Registries, applications, and supervisors](supervisor-and-application.md), we have learned that our project is backed by an application, which bundles our modules and specifies how your supervision tree starts and shuts down. Each application can also have its own configuration, which in Erlang/OTP (and therefore Elixir) is called "application environment".
17
17
18
18
We can use the application environment to configure our own application, as well as others. Let's see the application environment in practice. Create a file `config/runtime.exs` with the following:
19
19
@@ -210,7 +210,7 @@ There is one essential ingredient to wrap up our distributed key-value store. In
Elixir automatically connected the nodes together. This is easy to do in an IEx session when both nodes are running on the same machine but it requires more work in a production environment, where nodes will be in different IP addresses and may be started at any time.
213
+
Elixir automatically connected the nodes together. This is easy to do in an IEx session when both instances are running on the same machine but it requires more work in a production environment, where instances are on different machines which may be started at any time and running on different IP addresses.
214
214
215
215
Luckily for us, this is also a well-solved problem. For example, if you are using [the Phoenix web framework](https://phoenixframework.org) in production, it ships with [the `dns_cluster` package](https://github.com/phoenixframework/dns_cluster), which automatically runs DNS queries to find new nodes and connect them. If you are using Kubernetes or cloud providers, [packages like `libcluster`](https://github.com/bitwalker/libcluster) ship with different strategies to discover and connect nodes.
216
216
@@ -249,7 +249,7 @@ mix deps.update # Updates the given dependencies
249
249
250
250
The most common tasks are `mix deps.get` and `mix deps.update`. Once fetched, dependencies are automatically compiled for you. You can read more about deps by running `mix help deps`.
251
251
252
-
To wrap up this chapter, we will build a very simple node discovery mechanism, where the name of the nodes we are should connect to are given on boot, using the lessons we learned in this chapter.
252
+
To wrap up this chapter, we will build a very simple node discovery mechanism, where the name of the nodes we should connect to are given on boot, using the lessons we learned in this chapter.
And they should connect to each other. Give it a try!
288
288
289
-
In an actual production system, there is some additional care we must take. For example, `--sname` only allows instances on the same machine to connect. For production, we would use `--name` instead.
289
+
In an actual production system, there is some additional care we must take. For example, we often use `--name` instead of `--sname` and give fully qualified node names.
290
290
291
291
Furthermore, when connecting two instances, we must guarantee they have the same cookie, which is a secret Erlang uses to authorize the connection. When they run on the same machine, they share the same cookie by default, but it must be either explicitly set or shared in other ways when deploying in a cluster.
Copy file name to clipboardExpand all lines: lib/elixir/pages/mix-and-otp/docs-tests-and-with.md
+1-4Lines changed: 1 addition & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -292,9 +292,6 @@ You can read more about `with/1` in our documentation.
292
292
The last step is to implement `KV.Command.run/1` to run the parsed commands on top of buckets. Its implementation is shown below:
293
293
294
294
```elixir
295
-
@doc """
296
-
Runs the given command.
297
-
"""
298
295
@doc """
299
296
Runs the given command.
300
297
"""
@@ -416,7 +413,7 @@ end
416
413
417
414
Run `mix test` and the tests should all pass. However, make sure to terminate any `iex -S mix` session you may have running, as currently tests and development environment are running on the same port (4040). We will address it in the next chapter.
418
415
419
-
We added three tests, the first one tests most bucket actions, while the other two deal with error cases. Given there is a lot of shared setup across these tests, we used the `setup/2` macro to deal with common boilerplate. The macro receives the same *test context* as tests and starts a client TCP connection per test. It also defines a unique bucket name using the module name and the test name, making sure any space in the test name is replaced by `-`.
416
+
We added three tests, the first one tests most bucket actions, while the other two deal with error cases. Given there is a lot of shared setup across these tests, we used the `setup/2` macro to deal with common boilerplate. The macro receives the same *test context* as tests and starts a client TCP connection per test. It also defines a unique bucket name using the module name and the test name, making sure any space in the test name is replaced by `-` as to not interfere with our command parsing logic.
420
417
421
418
Then, in each test, we pattern matched on the *test context*, extracting the socket or name as necessary. This is similar to the code we wrote in `test/kv/bucket_test.exs`:
Copy file name to clipboardExpand all lines: lib/elixir/pages/mix-and-otp/dynamic-supervisor.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@
5
5
6
6
# Supervising dynamic children
7
7
8
-
We have successfully learned how our supervisor tree is automatically started (and stopped) as part of our application's life cycle. We can also name our buckets via the `:name` option. We also learned that, in practice, we should always start new processes inside supervisors. Let's apply these insights by ensuring our buckets are named and supervised.
8
+
We have successfully learned how our supervision tree is automatically started (and stopped) as part of our application's life cycle. We can also name our buckets via the `:name` option. We also learned that, in practice, we should always start new processes inside supervisors. Let's apply these insights by ensuring our buckets are named and supervised.
Let's try to start it as part of a supervisor then, using the `{module, options}` format:
42
+
Let's try to start it as part of a supervisor then, using the `{module, options}` format to pass the bucket name (let's also use an atom as the name for convenience):
Overall, processes can be named and supervised, regardless if they are supervisors, agents, etc, since all of Elixir standard library was designed around those capabilities.
106
106
107
-
With all ingredients in place to supervise and name buckets, open up the `lib/kv.ex` module and let's add a new function called `KV.locate/1`, which receives a name and either create or returns a bucket for the given name:
107
+
With all ingredients in place to supervise and name buckets, open up the `lib/kv.ex` module and let's add a new function called `KV.lookup_bucket/1`, which receives a name and either create or returns a bucket for the given name:
108
108
109
109
```elixir
110
110
defmoduleKVdo
@@ -138,7 +138,7 @@ defmodule KV do
138
138
end
139
139
```
140
140
141
-
The code is relatively simple. First we changed `start/2` to also start a dynamic supervisor named `KV.BucketSupervisor`. Then, when implemented `KV.create_bucket/1` which receives a bucket and starts with using our registry and dynamic supervisor. And we also added `KV.locate_bucket/1` that receives the same name and attempts to find its PID.
141
+
The code is relatively simple. First we changed `start/2` to also start a dynamic supervisor named `KV.BucketSupervisor`. Then, when implemented `KV.create_bucket/1` which receives a bucket and starts with using our registry and dynamic supervisor. And we also added `KV.lookup_bucket/1` that receives the same name and attempts to find its PID.
142
142
143
143
To make sure it all works as expected, let's write a test. Open up `test/kv_test.exs` and add this:
144
144
@@ -160,7 +160,7 @@ end
160
160
161
161
The test shows we are creating and locating buckets with any name, making sure we use a unique name to avoid conflicts between tests.
162
162
163
-
## `start_supervised/1`
163
+
## The `start_supervised` test helper
164
164
165
165
Before we move on, let's do some clean up.
166
166
@@ -229,4 +229,4 @@ We will leave it up to you to further explore what Observer provides. Note you c
229
229
230
230
At the end of the day, tools like Observer are one of the reasons you want to always start processes inside supervision trees, even if they are temporary, to ensure they are always reachable and introspectable.
231
231
232
-
Now that our buckets are named and supervised, we are ready to start our server and start receiving request.
232
+
Now that our buckets are named and supervised, we are ready to start our server and start receiving requests.
0 commit comments