exercism/elixir/take-a-number-deluxe/HINTS.md

5.5 KiB

Hints

General

1. Start the machine

  • Remember to use the GenServer behaviour.
  • There is a built-in function that starts a linked GenServer process. The only thing that TakeANumberDeluxe.start_link/2 needs to do is call that function with the right arguments.
  • __MODULE__ is a special variable that holds the name of the current module.
  • Implement the GenServer callback used when starting the process.
  • The callback should return either {:ok, state} or {:stop, reason}.
  • Read the options from the init_arg keyword list.
  • There is a built-in function to get a value from a keyword list.
  • Use TakeANumberDeluxe.State.new/2 to get the initial state.
  • Use @impl above your callback implementation to mark which behaviour this callback comes from.

2. Report machine state

  • There is a built-in function that sends a message to a GenServer process and receives a reply. The only thing that TakeANumberDeluxe.report_state/1 needs to do is call that function with the right arguments.
  • The messages sent to a server can be anything, but atoms are best.
  • Implement the GenServer callback used when handling messages that need a reply.
  • The callback should return {:reply, reply, state}.
  • Pass the state as the reply.
  • Use @impl above your callback implementation to mark which behaviour this callback comes from.

3. Queue new numbers

  • There is a built-in function that sends a message to a GenServer process and receives a reply. The only thing that TakeANumberDeluxe.queue_new_number/1 needs to do is call that function with the right arguments.
  • The messages sent to a server can be anything, but atoms are best.
  • Implement the GenServer callback used when handling messages that need a reply.
  • The callback should return {:reply, reply, state}.
  • Get the reply and the new state by calling TakeANumberDeluxe.State.queue_new_number/1. Use a case expression to pattern match the return value.
  • The reply should be either {:ok, new_number} or {:error, error}.
  • Use @impl above your callback implementation to mark which behaviour this callback comes from.

4. Serve next queued number

  • There is a built-in function that sends a message to a GenServer process and receives a reply. The only thing that TakeANumberDeluxe.serve_next_queued_number/2 needs to do is call that function with the right arguments.
  • The messages sent to a server can be anything, but tuples are best if an argument needs to be sent in the message. Use a message like this: {:my_message_name, some_argument}.
  • Implement the GenServer callback used when handling messages that need a reply.
  • The callback should return {:reply, reply, state}.
  • Get the reply and the new state by calling TakeANumberDeluxe.State.serve_next_queued_number/2. Use a case expression to pattern match the return value.
  • The reply should be either {:ok, next_number} or {:error, error}.
  • Use @impl above your callback implementation to mark which behaviour this callback comes from.

5. Reset state

  • There is a built-in function that sends a message to a GenServer process and does not wait for a reply. The only thing that TakeANumberDeluxe.reset_state/1 needs to do is call that function with the right arguments.
  • The messages sent to a server can be anything, but atoms are best.
  • Implement the GenServer callback used when handling messages that do not need a reply.
  • The callback should return {:noreply, state}.
  • Use TakeANumberDeluxe.State.new/2 to get the new state, just like in init/1.
  • Use @impl above your callback implementation to mark which behaviour this callback comes from.

6. Implement auto shutdown

  • Extend all init/1 and handle_* callbacks to return one extra element in their tuples. Its value should be state.auto_shutdown_timeout.
  • The return value {:stop, reason} of init/1 does not need a timeout.
  • Implement the GenServer callback used when handling messages that weren't sent in the usual GenServer way.
  • This callback needs to handle :timeout messages and exit the process, but also catch and ignore any other messages.
  • To exit a GenServer process, return {:stop, reason, state} from the callback.
  • The exit reason should be :normal.