Of course. Pivoting back to internal technical documentation, the next step is to create a comprehensive list of diagrams and technical specifications that will serve as the detailed blueprint for the Layer 1 implementation team.
This list goes deeper than the high-level architectural diagrams, focusing on the specific internal mechanics, data flows, and process interactions required to build a robust foundation. Creating these diagrams first ensures that all engineers on the team share a common understanding of the system’s internals before a single line of code is written.
Technical Blueprint: Required Diagrams for DSPEx
Layer 1
This document outlines the full set of technical diagrams needed for the implementation of DSPEx
v0.1. These diagrams will detail process supervision, data structures, state transitions, and component interactions.
I. OTP Supervision & Process Architecture
These diagrams focus on the lifecycle and relationships of the concurrent processes that make up the system.
Application Supervision Tree Diagram:
- Purpose: To show the static OTP supervision hierarchy at application boot.
- Type: Component Diagram (or simple tree diagram).
- Content:
- Root
MyApp.Application
supervisor. - Child
MyApp.Supervisor
. - Child
DSPEx.Client.LM
GenServer process, showing its registration name (e.g.,MyClient
). - Child
DSPEx.Cache
GenServer process (to be detailed in Layer 2, but we can placeholder it). - Clearly indicate restart strategies (e.g.,
:one_for_one
).
- Root
Dynamic Request Process Tree Diagram:
- Purpose: To illustrate the temporary process hierarchy created for a single
DSPEx.Program.forward/2
call. - Type: Component Diagram or Process Interaction Diagram.
- Content:
- The user’s calling process (e.g., from an
IEx
session or a Phoenix controller). - The spawned
ProgramProcess
(which executes theforward
logic). - The link between the
ProgramProcess
and theI/O Task
it spawns for the LM call. - Clearly label the supervision relationship (
ProgramProcess
supervisesI/O Task
).
- The user’s calling process (e.g., from an
- Purpose: To illustrate the temporary process hierarchy created for a single
LM Client
GenServer
State Diagram:- Purpose: To model the internal state and transitions of the
DSPEx.Client.LM
process. - Type: State Machine Diagram.
- Content:
- States:
:initializing
,:idle
,:busy
(though it offloads work, it might have internal states for managing a request queue in the future). - Transitions:
start_link/1
->:initializing
->:idle
. - Events:
handle_cast({:request, ...})
,handle_info({:DOWN, ...})
from monitored tasks.
- States:
- Purpose: To model the internal state and transitions of the
II. Data Structures & Data Flow
These diagrams detail the structure of data as it moves through the system.
DSPEx.Signature
Macro Expansion Diagram:- Purpose: To provide a crystal-clear, step-by-step visual of the metaprogramming transformation.
- Type: Flowchart or Data Flow Diagram.
- Content:
- Input: Developer’s source code (
use DSPEx.Signature, "..."
). - Process Step 1: Macro
__using__/1
is invoked by the compiler. - Process Step 2: String parsing (
String.split
, Regex) to extract input/output fields. - Process Step 3: Capture
@moduledoc
. - Process Step 4: Generate Elixir AST using
quote
andunquote
. - Output: The final code injected into the calling module (structs, functions, behaviour implementation).
- Input: Developer’s source code (
End-to-End Data Transformation Diagram (
Predict
call):- Purpose: To trace the data format at each step of a
forward/2
call. - Type: Data Flow Diagram.
- Content:
inputs :: map
(User input).DSPEx.Predict
:messages :: list(map)
(Formatted for LM API).
DSPEx.Client.LM
:http_body :: json_string
(Sent to provider).http_response :: json_string
(Received from provider).completion_map :: map
(Parsed response).
DSPEx.Predict
(Return Path):%DSPEx.Prediction{}
(Final structured output).
- Each arrow should be annotated with the function/process responsible for the transformation.
- Purpose: To trace the data format at each step of a
III. Sequence & Interaction Diagrams
These diagrams focus on the timing and order of messages and function calls between components.
Application Startup Sequence Diagram:
- Purpose: To show the sequence of events when the Elixir application boots.
- Type: Sequence Diagram.
- Content:
- Participants:
mix
,MyApp.Application
,MyApp.Supervisor
,DSPEx.Client.LM
. - Sequence:
mix
callsApplication.start/2
, which starts its childSupervisor
, which in turn callsstart_link
on theLM
client, registering its name.
- Participants:
Successful
Predict.forward
Sequence Diagram:- Purpose: To detail the message-passing for a successful, end-to-end execution.
- Type: Sequence Diagram.
- Content:
- Participants:
User Process
,ProgramProcess
(forPredict
),LM_Client GenServer
,I/O Task
. - Sequence:
User
callsforward
.ProgramProcess
callsLM_Client.request
.LM_Client
receivescast
message.LM_Client
spawns supervisedI/O Task
.I/O Task
makes HTTP call.I/O Task
sends{:ok, response}
message toProgramProcess
.ProgramProcess
receives the message.ProgramProcess
formats thePrediction
and returns it.
- Participants:
Predict.forward
with I/O Failure & Crash Sequence Diagram:- Purpose: To explicitly model the “let it crash” philosophy for transient errors. This is the most important diagram for understanding OTP benefits.
- Type: Sequence Diagram.
- Content:
- Same participants as above.
- Sequence:
- …up to the
I/O Task
making the HTTP call. I/O Task
’s HTTP client raises an exception (e.g.,:econnrefused
), causing the task to crash.- The BEAM sends a
{:DOWN, ref, :process, pid, :normal | :error_reason}
message to the supervisingProgramProcess
. ProgramProcess
’sreceive
block (or atry/rescue
aroundTask.await
) catches this failure.ProgramProcess
decides not to crash itself and instead initiates retry logic (this will be implemented in Layer 2, but we design for it now).
- …up to the
Implementation Plan
Once this comprehensive set of diagrams is completed and reviewed by the team, the implementation of Layer 1 can begin. The development will proceed in the order outlined in the engineering plan, using these diagrams as the definitive guide for each component’s internal logic and its public interface.
- Develop
DSPEx.Settings
and the coreExample
/Prediction
structs. (Corresponds to Diagram #5 data structures). - Implement the
DSPEx.Signature
macro. (Corresponds to Diagram #4). - Build the basic
DSPEx.Client.LM
GenServer. (Corresponds to Diagrams #1, #3, #6). - Implement the
DSPEx.Predict
module and itsforward
function. (Corresponds to Diagrams #2, #7, #8). - Write unit and integration tests that validate the behavior shown in every diagram.
This structured approach ensures that the foundational layer is not just functional, but also architecturally sound, testable, and perfectly aligned with the principles of OTP.