Skip to content

Commit 0d83f04

Browse files
committed
Sync issues
1 parent 0433da5 commit 0d83f04

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
number: 5
3+
title: "Unified Server/Client Interaction API Refactoring"
4+
state: open
5+
labels:
6+
---
7+
8+
## 1. Problem Description
9+
The current API for defining client-side logic (`@app.client`, `@app.startup`) and server-side interactions (`@app.server`, `@app.connect`) is functional but lacks a cohesive structural philosophy.
10+
* It is not immediately obvious which functions are RPC endpoints versus fire-and-forget signals.
11+
* There is no unified way to handle custom events (e.g., "game_started", "user_joined") other than raw WebSocket hooks.
12+
* Client-side DOM event handlers lack validation, leading to potential runtime errors if a user attaches a non-async or non-client function to an element.
13+
14+
## 2. Proposed Design
15+
We will consolidate all interaction logic under two main namespaces: `@app.server` and `@app.client`. This creates a clear mental model: "Where does this code run?" and "How is it triggered?"
16+
17+
### 2.1 Server-Side API (`@app.server`)
18+
Methods decorated here execute on the Python Backend (FastAPI).
19+
20+
* **`@app.server.rpc`**
21+
* **Behavior:** Exposed to the client via HTTP/Fetch.
22+
* **Contract:** Request/Response. The client `await`s this and receives a return value.
23+
* **Use Case:** Database queries, heavy computation, sensitive logic.
24+
25+
* **`@app.server.realtime`**
26+
* **Behavior:** Exposed to the client via WebSocket.
27+
* **Contract:** Fire-and-forget. The client calls this but **does not** wait for a result.
28+
* **Safety:** If the decorated function returns a value, the server logs a warning (data loss).
29+
* **Use Case:** High-frequency telemetry, keystrokes, broadcasting state updates.
30+
31+
* **`@app.server.on(event: str)`**
32+
* **Behavior:** Registers a handler for lifecycle or custom events.
33+
* **Lifecycle Events:** `"start"`, `"stop"`, `"connect"`, `"disconnect"`.
34+
* **Custom Events:** Triggered via `app.emit(event, data)`.
35+
36+
### 2.2 Client-Side API (`@app.client`)
37+
Methods decorated here are transpiled/sent to the browser (Pyodide).
38+
39+
* **`@app.client`** (Base)
40+
* **Behavior:** Marks function for transpilation. Callable by other client-side code.
41+
42+
* **`@app.client.callback`**
43+
* **Behavior:** Specific marker for DOM Event Listeners.
44+
* **Validation:** The DOM binder (e.g., `div.on("click", func)`) must check for this decorator. If missing, raise `ValueError` to prevent runtime hydration errors.
45+
46+
* **`@app.client.realtime`**
47+
* **Behavior:** Registers the function as a target for Server-to-Client WebSocket calls (Reverse RPC).
48+
* **Contract:** Fire-and-forget. The server calls this to push updates to the browser.
49+
* **Use Case:** Updating UI based on server state changes, notifications.
50+
51+
* **`@app.client.on(event: str)`**
52+
* **Behavior:** Registers a handler for client-side events.
53+
* **Lifecycle Events:** `"ready"` (hydration done), `"connect"`, `"disconnect"`.
54+
55+
### 2.3 Runtime & Internals
56+
* **`window.violetear`**: The JavaScript global object acting as the Single Source of Truth for the client.
57+
* **`violetear.runtime`**:
58+
* **`get_runtime()`**: Returns a proxy to `window.violetear` (available only in Browser).
59+
* **`runtime.emit(event, data)`**: Allows Python client code to trigger the JS event bus.
60+
61+
## 3. Implementation Roadmap
62+
63+
### Phase 1: Core Refactoring (`violetear/app.py`)
64+
- [ ] Create `Server` and `Client` nested classes within `App` to handle the new decorator syntax.
65+
- [ ] Deprecate old decorators (`@app.startup`, `@app.connect`) in favor of lifecycle events (`@app.client.on("ready")`, `@app.server.on("connect")`).
66+
67+
### Phase 2: Event Bus & Runtime (`violetear/client.py`)
68+
- [ ] Implement `window.violetear` in the JS bundle to manage event listeners.
69+
- [ ] Implement `violetear.runtime` module for Python access to the event bus.
70+
- [ ] Implement Message Queue: Ensure `emit` calls made before the socket connects are buffered and flushed upon connection.
71+
72+
### Phase 3: Communication Layer (`SocketManager`)
73+
- [ ] Update `SocketManager` to distinguish between `rpc` (fetch) and `realtime` (websocket) messages.
74+
- [ ] Implement the "Reverse RPC" mechanism for `@app.client.realtime`.
75+
76+
## 4. Considerations & Constraints
77+
* **Serialization:** Events and Realtime calls are limited to JSON-serializable data.
78+
* **Ambiguity:** Ensure strict warnings if a user tries to `await` a `realtime` function (client-side stubs should return `None`).
79+
* **Execution Order:** Ensure handlers for `"ready"` and `"connect"` fire reliably regardless of network race conditions (client loads faster/slower than socket connects).

0 commit comments

Comments
 (0)