Mailbox Server
Mix.install([
{:jason, "~> 1.4"},
{:kino, "~> 0.9", override: true},
{:youtube, github: "brooklinjazz/youtube"},
{:hidden_cell, github: "brooklinjazz/hidden_cell"}
])
Navigation
Home Report An Issue Asynchronous MessagesScore TrackerMailbox Server
Earlier you created a Process Mailbox using purely processes. Now you’re going to create a similar mailbox using GenServer.
To test your solution, you can use :sys.get_state/1 to get the current state of your mailbox. This should only be used for debugging purposes, not for retrieving values from state in a real-world application.
{:ok, mailbox_pid} = GenServer.start_link(Mailbox, [])
GenServer.cast(mailbox_pid, {:mail, %{title: "Title 1", content: "Content 1"}})
GenServer.cast(mailbox_pid, {:mail, %{title: "Title 2", content: "Content 2"}})
:sys.get_state(mailbox_pid)
[%{title: "Title 2", content: "Content 2"}, %{title: "Title 1", content: "Content 1"}]
Example Solution
defmodule Mailbox do
use GenServer
def start_link(state \\ []) do
GenServer.start_link(__MODULE__, state)
end
def send(mailbox_pid, mail) do
GenServer.cast(mailbox_pid, {:mail, mail})
end
def all_messages(mailbox_pid) do
GenServer.call(mailbox_pid, :all_messages)
end
@impl true
def init(state) do
{:ok, state}
end
@impl true
def handle_call(:all_messages, _from, state) do
{:noreply, state, state}
end
@impl true
def handle_cast({:mail, mail}, state) do
{:noreply, [mail | state]}
end
def handle_info({:mail, mail}, state) do
{:noreply, [mail | state]}
end
end
Implement the Mailbox
GenServer as documented below.
defmodule Mailbox do
use GenServer
@doc """
Start a mailbox server.
## Examples
iex> {:ok, pid} = Mailbox.start_link([])
iex> :sys.get_state(pid)
[]
Allow the mailbox to start with a default list of messages.
iex> {:ok, pid} = Mailbox.start_link(["Welcome to your mailbox!"])
iex> :sys.get_state(pid)
["Welcome to your mailbox!"]
"""
def start_link(_opts) do
end
@doc """
Asynchronously Send a message to a mailbox server.
## Examples
iex> {:ok, pid} = Mailbox.start_link([])
iex> Mailbox.send(pid, "Message 1")
iex> Mailbox.send(pid, "Message 2")
iex> :sys.get_state(pid)
["Message 2", "Message 1"]
"""
def send(mailbox_pid, message) do
end
@doc """
Synchonously retrieve all messages in a mailbox server.
## Examples
iex> {:ok, pid} = Mailbox.start_link([])
iex> Mailbox.all_messages(pid)
[]
"""
def all_messages(mailbox_pid) do
end
@doc """
Required callback to start a GenServer.
## Examples
iex> {:ok, _pid} = GenServer.start_link(Mailbox, [])
"""
@impl true
def init(state) do
end
@doc """
Callback to synchronously retrieve a `Mailbox`'s state.
## Examples
iex> {:ok, pid} = GenServer.start_link(Mailbox, ["Welcome"])
iex> GenServer.call(pid, :all_messages)
["Welcome"]
"""
@impl true
def handle_call(:all_messages, _from, state) do
end
@doc """
Callback for receiving a `cast` message and storing it in the `Mailbox`'s state.
## Examples
iex> {:ok, pid} = GenServer.start_link(Mailbox, [])
iex> GenServer.cast(pid, {:mail, "Message 1"})
iex> GenServer.cast(pid, {:mail, "Message 2"})
iex> :sys.get_state(pid)
["Message 2", "Message 1"]
"""
@impl true
def handle_cast({:mail, mail}, state) do
end
@doc """
Callback for receiving "regular" messages and storing them in the `Mailbox`'s state.
## Examples
iex> {:ok, pid} = GenServer.start_link(Mailbox, [])
iex> Process.send(pid, {:mail, "Message 1"}, [])
iex> Process.send(pid, {:mail, "Message 2"}, [])
iex> :sys.get_state(pid)
["Message 2", "Message 1"]
"""
@impl true
def handle_info({:mail, mail}, state) do
end
end
Commit Your Progress
DockYard Academy now recommends you use the latest Release rather than forking or cloning our repository.
Run git status
to ensure there are no undesirable changes.
Then run the following in your command line from the curriculum
folder to commit your progress.
$ git add .
$ git commit -m "finish Mailbox Server exercise"
$ git push
We’re proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace.
We also offer a paid course where you can learn from an instructor alongside a cohort of your peers. We will accept applications for the June-August 2023 cohort soon.