201 lines
11 KiB
Markdown
201 lines
11 KiB
Markdown
# Architecture: Circle Management System
|
|
|
|
## 1. Introduction & Overview
|
|
|
|
This document outlines the architecture for a system that manages multiple "Circles." Each Circle is an independent entity comprising its own database, a Rhai scripting engine, a dedicated Rhai worker process, and a WebSocket (WS) server for external interaction. A central command-line orchestrator will be responsible for initializing, running, and monitoring these Circles based on a configuration file.
|
|
|
|
The primary goal is to allow users to define multiple isolated Rhai environments, each accessible via a unique WebSocket endpoint, and for scripts executed within a circle to interact with that circle's dedicated persistent storage.
|
|
|
|
## 2. Goals
|
|
|
|
* Create a command-line application (`circles_orchestrator`) to manage the lifecycle of multiple Circles.
|
|
* Each Circle will have:
|
|
* An independent `OurDB` instance for data persistence.
|
|
* A dedicated `Rhai Engine` configured with its `OurDB`.
|
|
* A dedicated `Rhai Worker` processing scripts for that circle.
|
|
* A dedicated `WebSocket Server` exposing an endpoint for that circle.
|
|
* Circle configurations (name, ID, port) will be loaded from a `circles.json` file.
|
|
* The orchestrator will display a status table of all running circles, including their worker queue and WS server URL.
|
|
* Utilize existing crates (`ourdb`, `rhai_engine`, `rhai_worker`, `rhai_client`, `server_ws`) with necessary refactoring to support library usage.
|
|
|
|
## 3. System Components
|
|
|
|
* **Orchestrator (`circles_orchestrator`)**:
|
|
* Location: `/Users/timurgordon/code/git.ourworld.tf/herocode/circles/cmd/src/main.rs`
|
|
* Role: Parses `circles.json`, initializes, spawns, and monitors all components for each defined circle. Displays system status.
|
|
* **Circle Configuration (`circles.json`)**:
|
|
* Location: e.g., `/Users/timurgordon/code/git.ourworld.tf/herocode/circles/cmd/circles.json`
|
|
* Role: Defines the set of circles to be managed, including their ID, name, and port.
|
|
* **OurDB (Per Circle)**:
|
|
* Library: `/Users/timurgordon/code/git.ourworld.tf/herocode/db/ourdb/src/lib.rs`
|
|
* Role: Provides persistent key-value storage for each circle, configured in incremental mode. Instance data stored at `~/.hero/circles/{id}/`.
|
|
* **Rhai Engine (Per Circle)**:
|
|
* Library: `/Users/timurgordon/code/git.ourworld.tf/herocode/rhailib/src/engine/src/lib.rs`
|
|
* Role: Provides the Rhai scripting environment for a circle, configured with the circle's specific `OurDB` instance.
|
|
* **Rhai Worker (Per Circle)**:
|
|
* Library: `/Users/timurgordon/code/git.ourworld.tf/herocode/rhailib/src/worker/src/lib.rs`
|
|
* Role: Executes Rhai scripts for a specific circle. Listens on a dedicated Redis queue for tasks and uses the circle's `Rhai Engine`.
|
|
* **Rhai Client (Per Circle WS Server)**:
|
|
* Library: `/Users/timurgordon/code/git.ourworld.tf/herocode/rhailib/src/client/src/lib.rs`
|
|
* Role: Used by a `Circle WebSocket Server` to send script execution tasks to its corresponding `Rhai Worker` via Redis.
|
|
* **Circle WebSocket Server (Per Circle)**:
|
|
* Library: `/Users/timurgordon/code/git.ourworld.tf/herocode/circles/server_ws/src/lib.rs`
|
|
* Role: Exposes a WebSocket endpoint for a specific circle, allowing external clients to submit Rhai scripts for execution within that circle.
|
|
* **Redis**:
|
|
* URL: `redis://127.0.0.1:6379`
|
|
* Role: Acts as the message broker between `Rhai Clients` (within WS Servers) and `Rhai Workers`.
|
|
|
|
## 4. High-Level Design Aspects
|
|
|
|
### 4.1. Orchestrator Logic (Conceptual)
|
|
The `circles_orchestrator` reads the `circles.json` configuration. For each defined circle, it:
|
|
1. Determines the `OurDB` path based on the circle's ID.
|
|
2. Initializes the `OurDB` instance.
|
|
3. Creates a `Rhai Engine` configured with this `OurDB`.
|
|
4. Spawns a `Rhai Worker` task, providing it with the engine and the circle's identity (for Redis queue naming).
|
|
5. Spawns a `Circle WebSocket Server` task, providing it with the circle's identity and port.
|
|
It then monitors these components and displays their status.
|
|
|
|
### 4.2. Database Path Convention
|
|
* Base: System user's home directory (e.g., `/Users/username` or `/home/username`).
|
|
* Structure: `~/.hero/circles/{CIRCLE_ID}/`
|
|
* Example: For a circle with ID `1`, the database path would be `~/.hero/circles/1/`.
|
|
|
|
### 4.3. Configuration File Format (`circles.json`)
|
|
A JSON array of objects. Each object represents a circle:
|
|
* `id`: `u32` - Unique identifier.
|
|
* `name`: `String` - Human-readable name.
|
|
* `port`: `u16` - Port for the WebSocket server.
|
|
```json
|
|
[
|
|
{ "id": 1, "name": "Alpha Circle", "port": 8081 },
|
|
{ "id": 2, "name": "Beta Circle", "port": 8082 }
|
|
]
|
|
```
|
|
|
|
### 4.4. Conceptual Output Table Format (Orchestrator)
|
|
| Circle Name | ID | Worker Status | Worker Queues | WS Server URL |
|
|
|--------------|----|---------------|------------------------------------|------------------------|
|
|
| Alpha Circle | 1 | Running | `rhai_tasks:alpha_circle` | `ws://127.0.0.1:8081/ws` |
|
|
|
|
### 4.5. Interaction Flow (Single Circle)
|
|
1. An external client connects to a specific Circle's WebSocket Server.
|
|
2. The client sends a Rhai script via a JSON-RPC message.
|
|
3. The WS Server uses its embedded `Rhai Client` to publish the script and task details to a Redis queue specific to that circle (e.g., `rhai_tasks:alpha_circle`).
|
|
4. The `Rhai Worker` for that circle picks up the task from its Redis queue.
|
|
5. The Worker uses its `Rhai Engine` (which is configured with the circle's `OurDB`) to execute the script.
|
|
6. Any database interactions within the script go through the circle's `OurDB`.
|
|
7. The Worker updates the task status and result/error in Redis.
|
|
8. The `Rhai Client` (in the WS Server), which has been polling Redis for the result, receives the update.
|
|
9. The WS Server sends the script's result or error back to the external client via WebSocket.
|
|
|
|
## 5. Diagrams
|
|
|
|
### 5.1. Component Diagram
|
|
```mermaid
|
|
graph TD
|
|
UserInterface[User/Admin] -- Manages --> OrchestratorCli{circles_orchestrator}
|
|
OrchestratorCli -- Reads --> CirclesJson[circles.json]
|
|
|
|
subgraph Circle 1
|
|
direction LR
|
|
OrchestratorCli -- Spawns/Manages --> C1_OurDB[(OurDB @ ~/.hero/circles/1)]
|
|
OrchestratorCli -- Spawns/Manages --> C1_RhaiEngine[Rhai Engine 1]
|
|
OrchestratorCli -- Spawns/Manages --> C1_RhaiWorker[Rhai Worker 1]
|
|
OrchestratorCli -- Spawns/Manages --> C1_WSServer[WS Server 1 @ Port 8081]
|
|
|
|
C1_RhaiEngine -- Uses --> C1_OurDB
|
|
C1_RhaiWorker -- Uses --> C1_RhaiEngine
|
|
C1_WSServer -- Contains --> C1_RhaiClient[Rhai Client 1]
|
|
end
|
|
|
|
subgraph Circle 2
|
|
direction LR
|
|
OrchestratorCli -- Spawns/Manages --> C2_OurDB[(OurDB @ ~/.hero/circles/2)]
|
|
OrchestratorCli -- Spawns/Manages --> C2_RhaiEngine[Rhai Engine 2]
|
|
OrchestratorCli -- Spawns/Manages --> C2_RhaiWorker[Rhai Worker 2]
|
|
OrchestratorCli -- Spawns/Manages --> C2_WSServer[WS Server 2 @ Port 8082]
|
|
|
|
C2_RhaiEngine -- Uses --> C2_OurDB
|
|
C2_RhaiWorker -- Uses --> C2_RhaiEngine
|
|
C2_WSServer -- Contains --> C2_RhaiClient[Rhai Client 2]
|
|
end
|
|
|
|
C1_RhaiWorker -- Listens/Publishes --> Redis[(Redis @ 127.0.0.1:6379)]
|
|
C1_RhaiClient -- Publishes/Subscribes --> Redis
|
|
C2_RhaiWorker -- Listens/Publishes --> Redis
|
|
C2_RhaiClient -- Publishes/Subscribes --> Redis
|
|
|
|
ExternalWSClient1[External WS Client] -- Connects --> C1_WSServer
|
|
ExternalWSClient2[External WS Client] -- Connects --> C2_WSServer
|
|
```
|
|
|
|
### 5.2. Sequence Diagram (Request Flow for one Circle)
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant ExtWSClient as External WS Client
|
|
participant CircleWSServer as Circle WS Server (e.g., Port 8081)
|
|
participant RhaiClientLib as Rhai Client Library (in WS Server)
|
|
participant RedisBroker as Redis
|
|
participant RhaiWorker as Rhai Worker (for the circle)
|
|
participant RhaiEngineLib as Rhai Engine Library (in Worker)
|
|
participant CircleOurDB as OurDB (for the circle)
|
|
|
|
ExtWSClient ->>+ CircleWSServer: Send Rhai Script (JSON-RPC "play" over WS)
|
|
CircleWSServer ->>+ RhaiClientLib: submit_script_and_await_result(circle_name, script, ...)
|
|
RhaiClientLib ->>+ RedisBroker: LPUSH rhai_tasks:circle_name (task_id)
|
|
RhaiClientLib ->>+ RedisBroker: HSET rhai_task_details:task_id (script details)
|
|
RhaiClientLib -->>- CircleWSServer: Returns task_id (internally starts polling)
|
|
|
|
RhaiWorker ->>+ RedisBroker: BLPOP rhai_tasks:circle_name (blocks)
|
|
RedisBroker -->>- RhaiWorker: Returns task_id
|
|
RhaiWorker ->>+ RedisBroker: HGETALL rhai_task_details:task_id
|
|
RedisBroker -->>- RhaiWorker: Returns script details
|
|
RhaiWorker ->>+ RhaiEngineLib: eval_with_scope(script)
|
|
RhaiEngineLib ->>+ CircleOurDB: DB Operations (if script interacts with DB)
|
|
CircleOurDB -->>- RhaiEngineLib: DB Results
|
|
RhaiEngineLib -->>- RhaiWorker: Script Result/Error
|
|
RhaiWorker ->>+ RedisBroker: HSET rhai_task_details:task_id (status="completed/error", output/error)
|
|
|
|
RhaiClientLib ->>+ RedisBroker: HGETALL rhai_task_details:task_id (polling)
|
|
RedisBroker -->>- RhaiClientLib: Task details (status, output/error)
|
|
alt Task Completed
|
|
RhaiClientLib -->>- CircleWSServer: Result (output)
|
|
CircleWSServer -->>- ExtWSClient: WS Response (JSON-RPC with result)
|
|
else Task Errored
|
|
RhaiClientLib -->>- CircleWSServer: Error (error message)
|
|
CircleWSServer -->>- ExtWSClient: WS Response (JSON-RPC with error)
|
|
else Timeout
|
|
RhaiClientLib -->>- CircleWSServer: Timeout Error
|
|
CircleWSServer -->>- ExtWSClient: WS Response (JSON-RPC with timeout error)
|
|
end
|
|
```
|
|
|
|
### 5.3. Conceptual Directory Structure
|
|
```
|
|
/Users/timurgordon/code/git.ourworld.tf/herocode/
|
|
├── circles/
|
|
│ ├── cmd/ <-- NEW Orchestrator Crate
|
|
│ │ ├── Cargo.toml
|
|
│ │ ├── circles.json (example config)
|
|
│ │ └── src/
|
|
│ │ └── main.rs (Orchestrator logic)
|
|
│ ├── server_ws/ <-- EXISTING, to be refactored to lib
|
|
│ │ ├── Cargo.toml
|
|
│ │ └── src/
|
|
│ │ └── lib.rs (WebSocket server library logic)
|
|
│ ├── ARCHITECTURE.md (This document)
|
|
│ └── README.md
|
|
├── db/
|
|
│ └── ourdb/
|
|
│ └── src/lib.rs (Existing OurDB library)
|
|
└── rhailib/ <-- Current Workspace (contains other existing libs)
|
|
├── src/
|
|
│ ├── client/
|
|
│ │ └── src/lib.rs (Existing Rhai Client library)
|
|
│ ├── engine/
|
|
│ │ └── src/lib.rs (Existing Rhai Engine library)
|
|
│ └── worker/
|
|
│ └── src/lib.rs (Existing Rhai Worker library, to be refactored)
|
|
├── Cargo.toml
|
|
└── ... |