On this page:
4.1 Using OTP Abstractions
4.2 Supervision
4.3 State Managment
4.4 Application & Client Interface
4.5 Delivery

E4 — OTP: Our Terrier Puppies

Due Tuesday, 16 April 2024, 11:59:59pm.

Purpose The purpose of this milestone is to improve the robustness of our animal center(s).

Programming Task

The first goal is to investigate and address test failures in milestones E2, E3, and 6.

The next is to revise the STBU implementation to conform to the OTP philosophy and best practices:

  1. Revising your implementation of the shelter and clinic interfaces to be based on GenServer;

  2. Deploying supervision to ensure one fault doesn’t break the entire system;

  3. State management to prevent faults from causing data loss; and

  4. Creating an Application that encapsulates the system.

4.1 Using OTP Abstractions

Your implementation of milestones E2 — Adoptions, Take 2 and E3 — Appointments, Take 2 spawns at least several processes to enable client interactions with the center’s shelter and clinic. Revise your implementations of these processes so that they are based on the abstractions provided by OTP, such as:

In other words, your implementation should no longer directly spawn processes. Instead, process behavior should be defined in terms of an OTP abstraction and then instantiated via that abstraction (such as the GenServer.start/3 or GenServer.start_link/3 functions).

4.2 Supervision

One malformed message or buggy function shouldn’t take down the entire adoption/clinic service for every client. In addition to our efforts to eliminate such errors from our system, we must also face the reality that we are (almost) never 100% confident in the absence of such faults. To deal with the situation, we will employ the OTP notion of supervision: watching over the health of the processes in our system and restarting them in the event of a failure.

Every process you create should be under the watch of a supervisor. That need not mean that the process must be restarted when it fails; refer to the child :restart options. You are also encouraged to remove any defensive programming you may have done in your solutions for the previous milestones.

4.3 State Managment

We can restart our processes when they crash, but their state will be lost. In some cases, that is OK; however, it would be quite unfortunate if all of the pets remaining at the shelter "disappeared" before finding their forever home (or if a client had to re-schedule their appointment). Such critical information should be insulated from the cycle of crashing and restarting that may occur with supervised processes.

On the other hand, the state of some processes has a more transient flavor that doesn’t seem to call for such care. For example, losing the progress of a PetViewer through the shelter or a client’s currentVet selection causes no lasting harm.

In light of these considerations, we will set the following goals:
  • The status of each pet in the shelter (available, playing, or adopted) should never be lost.

  • Likewise, booked appointments and currently reserved slots must be maintained.

  • If a client process exits for any reason, any PetViewer or AppointmentScheduler that it is interacting with should immediately perform any necessary clean up (like releasing a reserved-but-not-yet-booked appointment) and shutdown as well.

  • If a PetViewer or AppointmentScheduler process crashes, some other process should detect the failure and immediately perform any necessary clean up. The process should not be restarted, since:

  • Clients are left to deploy their own solution to monitor the status of their PetViewer/AppointmentScheduler process.

Devise a solution for your system to meet these goals. You may wish to draw inspiration from the key-value store example from class or the Stash from chapter 18 of Programming Elixir (see Readings).

4.4 Application & Client Interface

Finally, let’s package the system as an Elixir Application. Configure your project as an application named :stbu. When the application starts, it should initialize both the shelter and clinic processes and any related supervisors/helpers.

To configure the system, the application should read two items from its environment:

To reflect the center’s status as an application, we will modify the client interface to the shelter and clinic in the following manner:

The STBU.Interface.Entry interface may be ignored/removed.

4.5 Delivery

Your project should include the designated modules under the lib directory (see Elixir, Mix) with the behavior described above, and succesfully build (i.e. with mix compile).