Skip to content

Commit ad0640c

Browse files
docs(Mountain): Add technical deep dive document outlining core architecture and workflows
This commit introduces a comprehensive architecture guide for the Mountain backend, directly aligning with the final synthesized system design. The document: - Details Mountain's role as the Rust/Tauri implementation of Common traits - Explains core components like AppRuntime, MountainEnvironment, and Track dispatcher - Maps end-to-end workflows (e.g. terminal creation) to our effects-based architecture - Clarifies gRPC/Vine integration with Cocoon and Tauri/Wind communication patterns - Reinforces separation of concerns between environment providers and handler logic By formalizing these architectural decisions, we provide critical context for contributors while ensuring consistency with Land's declarative, capability-based design principles.
1 parent 7fccdfa commit ad0640c

1 file changed

Lines changed: 164 additions & 0 deletions

File tree

docs/Deep Dive.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<table><tr>
2+
<td colspan="1"> <h3 align="center"> <picture>
3+
<source media="(prefers-color-scheme: dark)" srcset="https://PlayForm.Cloud/Dark/Image/GitHub/Land.svg">
4+
<source media="(prefers-color-scheme: light)" srcset="https://PlayForm.Cloud/Image/GitHub/Land.svg">
5+
<img width="28" alt="Land Logo" src="https://PlayForm.Cloud/Image/GitHub/Land.svg">
6+
</picture> </h3> </td> <td colspan="3" valign="top"> <h3 align="center"> Mountain ⛰️
7+
</h3> </td>
8+
</tr></table>
9+
10+
# **Mountain** ⛰️ Deep Dive & Architecture
11+
12+
This document provides a detailed technical overview of the **Mountain** project
13+
for developers. It explores the internal architecture, the flow of control from
14+
request to execution, and the design patterns used to create a robust,
15+
effects-based native backend for the Land Code Editor.
16+
17+
## Core Architecture Principles
18+
19+
| Principle | Description | Key Components Involved |
20+
| :------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------- |
21+
| **Implementation of Contracts** | Faithfully implement the abstract service `trait`s defined in the `Common` crate, providing the concrete logic for the application's architecture. | `environment/*` providers |
22+
| **Separation of Concerns** | Isolate business logic in `handlers` modules, keeping the `environment` provider implementations clean and focused on delegation. | `environment/*`, `handlers/*` |
23+
| **Declarative Logic** | Express all operations as `ActionEffect`s, which are executed by the `AppRuntime`. This makes logic composable, testable, and robust. | `runtime/*`, `track/*`, `Common::effect` |
24+
| **Centralized State** | Maintain a single, thread-safe `AppState` struct managed by Tauri to ensure data consistency across the entire application. | `app_state/*` |
25+
| **Secure & Performant IPC** | Utilize gRPC for all communication with the `Cocoon` sidecar, ensuring a well-defined and high-performance API boundary. | `vine/*` |
26+
| **UI-Backend Decoupling** | Interact with the `Wind` frontend exclusively through asynchronous Tauri commands and events, ensuring the backend is UI-agnostic. | `main.rs` (invoke handler), `handlers/*` (emitters) |
27+
28+
---
29+
30+
## Deep Dive into `Mountain`'s Components
31+
32+
### 1. The `main.rs` Entry Point and Tauri Setup
33+
34+
- **Role:** This is the application's bootstrap sequence.
35+
- **Functionality:**
36+
- Initializes logging (`env_logger`).
37+
- Creates the `tauri::Builder` and configures the application.
38+
- Uses the `.setup()` hook as the primary initialization point. Inside this
39+
hook, it performs the critical task of creating the singleton instances of
40+
`AppState`, `MountainEnvironment`, and `AppRuntime` and placing them into
41+
Tauri's managed state (`AppHandle.manage(...)`).
42+
- Spawns a background `tokio` task for long-running initializations (like
43+
scanning for extensions and starting the gRPC server) to avoid blocking
44+
the main thread and allow the UI to appear faster.
45+
- Registers all Tauri command handlers (e.g., `track::DispatchCommand`),
46+
which are the entry points for requests coming from the `Wind` UI.
47+
- Handles application lifecycle events, such as `RunEvent::ExitRequested`.
48+
49+
### 2. The `runtime` and `environment` Modules (The Execution Core)
50+
51+
- **Role:** These two modules work together to form the execution engine for the
52+
application's logic.
53+
- **`runtime/`:**
54+
- `AppRuntime.rs` provides the concrete `AppRuntime` for `Mountain`. It
55+
holds an instance of the `MountainEnvironment`.
56+
- Its primary method, `Run`, takes an `ActionEffect` from the `Common`
57+
crate. It determines the required capability (e.g., `dyn FsReader`), gets
58+
it from its environment, and then applies the effect, executing the
59+
wrapped async function.
60+
- **`environment/`:**
61+
- `MountainEnvironment.rs` is the central struct that **implements all
62+
provider `trait`s** from `Common`. For example, it contains
63+
`impl FsReader for MountainEnvironment`.
64+
- **Crucially, the `impl` blocks in this module contain no business logic.**
65+
They are a clean "wiring" layer. Each method is a one-line call that
66+
delegates to a corresponding function in the `handlers` module (e.g.,
67+
`self.ReadFile(...)` calls `handlers::fs::ReadFileLogic(...)`).
68+
- `Utils.rs` contains shared helper functions used across multiple provider
69+
implementations, such as error mapping and security checks.
70+
71+
### 3. The `app_state` Module (The Single Source of Truth)
72+
73+
- **Role:** To provide a single, globally accessible, thread-safe container for
74+
all of the application's runtime state.
75+
- **Structure:**
76+
- The `AppState` struct contains fields like `WorkspaceFolders`,
77+
`Configuration`, `ActiveTerminals`, and `LanguageProviders`.
78+
- Every field is wrapped in `Arc<Mutex<...>>` (or `Arc<Atomic...>` for
79+
simple types) to allow for safe, shared access from any asynchronous task
80+
or thread in the application (e.g., a gRPC request handler and a Tauri
81+
command handler can both safely access `AppState`).
82+
- The `default()` implementation initializes the state, reads initial data
83+
from disk (like Memento storage), and sets up default values.
84+
85+
### 4. The `handlers` Module (The Business Logic Layer)
86+
87+
- **Role:** This is where the actual work gets done. By isolating logic here,
88+
the `environment` module remains clean, and the business logic is easy to
89+
find, read, and test.
90+
- **Functionality:**
91+
- Each submodule (`handlers/fs`, `handlers/terminal`, etc.) corresponds to a
92+
service domain.
93+
- Functions within these modules (e.g., `ReadFileLogic`,
94+
`CreateTerminalLogic`) perform the concrete operations. They take the
95+
`AppHandle` as an argument, which allows them to access `AppState`.
96+
- They interact with the native OS using crates like `tokio::fs`,
97+
`portable-pty`, and `keyring`.
98+
- After performing an operation and updating `AppState`, they are often
99+
responsible for emitting Tauri events to notify the `Wind` UI of the
100+
change (e.g., `AppHandle.emit("sky://terminal/data", ...)`).
101+
102+
### 5. The `vine` and `track` Modules (The Communication & Dispatch Layer)
103+
104+
- **Role:** These modules form the application's "front door" for all external
105+
requests coming from `Cocoon` and `Wind`.
106+
- **`vine/` (gRPC):**
107+
- `proto/vine.proto`: Defines the gRPC contract. It is the single source of
108+
truth for the `Mountain <-> Cocoon` API.
109+
- `build.rs`: Compiles the `.proto` file into Rust code using `tonic-build`.
110+
- `server/MountainVineGrpcService.rs`: Implements the `MountainService`
111+
trait generated by `tonic`. This is the gRPC request handler. When it
112+
receives a call (e.g., `ProcessCocoonRequest`), its only job is to pass
113+
the method name and parameters to the `track` dispatcher.
114+
- **`track/` (Dispatcher):**
115+
- `TrackLogic.rs` is the central router for the entire application. It
116+
exposes two primary functions: `DispatchCommand` (for Tauri invokes from
117+
`Wind`) and `DispatchSidecarRequest` (for gRPC calls from `Cocoon`).
118+
- **Dispatch Strategy:** When a request comes in, the dispatcher first
119+
consults `EffectCreation.rs`. It attempts to map the request's method name
120+
and parameters into a declarative `ActionEffect`. If a mapping exists, it
121+
passes the `ActionEffect` to the `AppRuntime` for execution.
122+
- **Fallback:** If no `ActionEffect` mapping is found (for legacy or highly
123+
specific RPCs), it falls back to a direct RPC handler system (not fully
124+
detailed in the synthesis, but this is the architectural slot for it).
125+
126+
---
127+
128+
## End-to-End Workflow Example: `CreateTerminal`
129+
130+
This demonstrates how all the components work together in a typical flow.
131+
132+
1. **Request Origin:** `Cocoon` sends a `CreateTerminal` gRPC request to
133+
`Mountain`.
134+
2. **Vine (gRPC Server):** `MountainVineGrpcService` receives the gRPC call. It
135+
extracts the method name (`"$createTerminal"`) and parameters. It passes
136+
these to `track::DispatchSidecarRequest`.
137+
3. **Track (Dispatcher):** The dispatcher looks up `"$createTerminal"` in
138+
`EffectCreation`. It finds a match and constructs a
139+
`Common::terminal::CreateTerminal` `ActionEffect`.
140+
4. **Runtime:** The dispatcher calls `AppRuntime.Run(effect)`.
141+
5. **Environment (Execution):**
142+
- The `AppRuntime` sees that the effect requires the `dyn TerminalProvider`
143+
capability.
144+
- It gets the `MountainEnvironment` and calls its `.Require()` method to get
145+
an `Arc<dyn TerminalProvider>`.
146+
- It applies the effect, which invokes the
147+
`TerminalProvider::CreateTerminal` method on the `MountainEnvironment`.
148+
6. **Provider (Delegation):** The
149+
`impl TerminalProvider for MountainEnvironment` block immediately delegates
150+
the call to `handlers::terminal::CreateTerminalLogic`, passing along its
151+
`AppHandle`.
152+
7. **Handler (Business Logic):**
153+
- The `CreateTerminalLogic` function performs the actual work.
154+
- It gets a new ID from `AppState`.
155+
- It uses `portable-pty` to spawn a native shell process.
156+
- It creates a `TerminalStateDto` and stores it in `AppState`.
157+
- It spawns `tokio` tasks to handle I/O streaming.
158+
- It sends gRPC notifications (`$acceptTerminalOpened`) back to `Cocoon`.
159+
- It emits Tauri events (`sky://terminal/create`) to `Wind`.
160+
- It returns a `Result` indicating success or failure.
161+
8. **Unwinding:** The `Result` unwinds back up the call stack: from the
162+
handler, through the environment, out of the `AppRuntime`, through the
163+
dispatcher, and finally, `MountainVineGrpcService` sends it back to `Cocoon`
164+
as the gRPC response.

0 commit comments

Comments
 (0)