portal, platform, and server fixes
This commit is contained in:
2692
circle/Cargo.lock
generated
Normal file
2692
circle/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
11
circle/Cargo.toml
Normal file
11
circle/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "circle"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
launcher = { path = "../../circles/src/launcher" }
|
||||
log = "0.4.14"
|
||||
tokio = { version = "1.42", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
68
circle/src/README.md
Normal file
68
circle/src/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# OurWorld Example
|
||||
|
||||
This directory contains a complete example demonstrating a simulated "OurWorld" network, consisting of multiple interconnected "circles" (nodes). Each circle runs its own WebSocket server and a Rhai script worker, all managed by a central launcher.
|
||||
|
||||
This example is designed to showcase:
|
||||
1. **Multi-Circle Configuration**: How to define and configure multiple circles in a single `circles.json` file.
|
||||
2. **Programmatic Launching**: How to use the `launcher` library to start, manage, and monitor these circles from within a Rust application.
|
||||
3. **Dynamic Key Generation**: The launcher generates unique cryptographic keypairs for each circle upon startup.
|
||||
4. **Output Generation**: How to use the `--output` functionality to get a JSON file containing the connection details (public keys, WebSocket URLs, etc.) for each running circle.
|
||||
5. **Graceful Shutdown**: How the launcher handles a `Ctrl+C` signal to shut down all running circles cleanly.
|
||||
|
||||
## Directory Contents
|
||||
|
||||
- `circles.json`: The main configuration file that defines the 7 circles in the OurWorld network, including their names, ports, and associated Rhai scripts.
|
||||
- `scripts/`: This directory contains the individual Rhai scripts that define the behavior of each circle.
|
||||
- `ourworld_output.json` (Generated): This file is created after running the example and contains the runtime details of each circle.
|
||||
|
||||
## How to Run the Example
|
||||
|
||||
There are two ways to run this example, each demonstrating a different way to use the launcher.
|
||||
|
||||
### 1. As a Root Example (Recommended)
|
||||
|
||||
This method runs the launcher programmatically from the root of the workspace and is the simplest way to see the system in action. It uses the `examples/ourworld.rs` file.
|
||||
|
||||
```sh
|
||||
# From the root of the workspace
|
||||
cargo run --example ourworld
|
||||
```
|
||||
|
||||
### 2. As a Crate-Level Example
|
||||
|
||||
This method runs a similar launcher, but as an example *within* the `launcher` crate itself. It uses the `src/launcher/examples/ourworld/main.rs` file. This is useful for testing the launcher in a more isolated context.
|
||||
|
||||
```sh
|
||||
# Navigate to the launcher's crate directory
|
||||
cd src/launcher
|
||||
|
||||
# Run the 'ourworld' example using cargo
|
||||
cargo run --example ourworld
|
||||
```
|
||||
|
||||
### 3. Using the Launcher Binary
|
||||
|
||||
This method uses the main `launcher` binary to run the configuration, which is useful for testing the command-line interface.
|
||||
|
||||
```sh
|
||||
# From the root of the workspace
|
||||
cargo run -p launcher -- --config examples/ourworld/circles.json --output examples/ourworld/ourworld_output.json
|
||||
```
|
||||
|
||||
## What to Expect
|
||||
|
||||
When you run the example, you will see log output indicating that the launcher is starting up, followed by a table summarizing the running circles:
|
||||
|
||||
```
|
||||
+-----------------+------------------------------------------------------------------+------------------------------------------+-----------------------+
|
||||
| Name | Public Key | Worker Queue | WS URL |
|
||||
+=================+==================================================================+==========================================+=======================+
|
||||
| OurWorld | 02... | rhai_tasks:02... | ws://127.0.0.1:9000/ws|
|
||||
+-----------------+------------------------------------------------------------------+------------------------------------------+-----------------------+
|
||||
| Dunia Cybercity | 03... | rhai_tasks:03... | ws://127.0.0.1:9001/ws|
|
||||
+-----------------+------------------------------------------------------------------+------------------------------------------+-----------------------+
|
||||
| ... (and so on for all 7 circles) |
|
||||
+-----------------+------------------------------------------------------------------+------------------------------------------+-----------------------+
|
||||
```
|
||||
|
||||
The launcher will then wait for you to press `Ctrl+C` to initiate a graceful shutdown of all services.
|
9
circle/src/circles.json
Normal file
9
circle/src/circles.json
Normal file
@@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"name": "Freezone",
|
||||
"port": 9000,
|
||||
"script_path": "scripts/freezone.rhai",
|
||||
"public_key": "030b62236efa67855b3379a9d4add1facbe8a545bafa86e1d6fbac06caae5b5b12",
|
||||
"secret_key": "04225fbb41d8c397581d7ec19ded8aaf02d8b9daf27fed9617525e4f8114a382"
|
||||
}
|
||||
]
|
90
circle/src/main.rs
Normal file
90
circle/src/main.rs
Normal file
@@ -0,0 +1,90 @@
|
||||
//! Example of launching multiple circles and outputting their details to a file.
|
||||
//!
|
||||
//! This example demonstrates how to use the launcher library to start circles
|
||||
//! programmatically, similar to how the `launcher` binary works.
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! ```sh
|
||||
//! cargo run --example ourworld
|
||||
//! ```
|
||||
//!
|
||||
//! This will:
|
||||
//! 1. Read the `circles.json` file in the `examples/ourworld` directory.
|
||||
//! 2. Launch all 7 circles defined in the config.
|
||||
//! 3. Create a `ourworld_output.json` file in the same directory with the details.
|
||||
//! 4. The launcher will run until you stop it with Ctrl+C.
|
||||
|
||||
use launcher::{run_launcher, Args, CircleConfig};
|
||||
use log::{error, info};
|
||||
use std::error::Error as StdError;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn StdError>> {
|
||||
println!("--- Launching OurWorld Example Programmatically ---");
|
||||
|
||||
// The example is now at the root of the `examples` directory,
|
||||
// so we can reference its assets directly.
|
||||
let example_dir = PathBuf::from("./src");
|
||||
let config_path = example_dir.join("circles.json");
|
||||
let output_path = example_dir.join("ourworld_output.json");
|
||||
|
||||
println!("Using config file: {:?}", config_path);
|
||||
println!("Output will be written to: {:?}", output_path);
|
||||
|
||||
// Manually construct the arguments instead of parsing from command line.
|
||||
// This is useful when embedding the launcher logic in another application.
|
||||
let args = Args {
|
||||
config_path: config_path.clone(),
|
||||
output: Some(output_path),
|
||||
debug: true, // Enable debug logging for the example
|
||||
verbose: 2, // Set verbosity to max
|
||||
};
|
||||
|
||||
if !config_path.exists() {
|
||||
let msg = format!("Configuration file not found at {:?}", config_path);
|
||||
error!("{}", msg);
|
||||
return Err(msg.into());
|
||||
}
|
||||
|
||||
let config_content = fs::read_to_string(&config_path)?;
|
||||
|
||||
let mut circle_configs: Vec<CircleConfig> = match serde_json::from_str(&config_content) {
|
||||
Ok(configs) => configs,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to parse {}: {}. Ensure it's a valid JSON array of CircleConfig.",
|
||||
config_path.display(),
|
||||
e
|
||||
);
|
||||
return Err(Box::new(e) as Box<dyn StdError>);
|
||||
}
|
||||
};
|
||||
|
||||
// Make script paths relative to the project root by prepending the example directory path.
|
||||
for config in &mut circle_configs {
|
||||
if let Some(script_path) = &config.script_path {
|
||||
let full_script_path = example_dir.join(script_path);
|
||||
config.script_path = Some(full_script_path.to_string_lossy().into_owned());
|
||||
}
|
||||
}
|
||||
|
||||
if circle_configs.is_empty() {
|
||||
info!(
|
||||
"No circle configurations found in {}. Exiting.",
|
||||
config_path.display()
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("Starting launcher... Press Ctrl+C to exit.");
|
||||
|
||||
// The run_launcher function will setup logging, spawn circles, print the table,
|
||||
// and wait for a shutdown signal (Ctrl+C).
|
||||
run_launcher(args, circle_configs).await?;
|
||||
|
||||
println!("--- OurWorld Example Finished ---");
|
||||
Ok(())
|
||||
}
|
8
circle/src/ourworld_output.json
Normal file
8
circle/src/ourworld_output.json
Normal file
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"name": "Freezone",
|
||||
"public_key": "030b62236efa67855b3379a9d4add1facbe8a545bafa86e1d6fbac06caae5b5b12",
|
||||
"worker_queue": "rhai_tasks:030b62236efa67855b3379a9d4add1facbe8a545bafa86e1d6fbac06caae5b5b12",
|
||||
"ws_url": "ws://127.0.0.1:9000"
|
||||
}
|
||||
]
|
10
circle/src/scripts/freezone.rhai
Normal file
10
circle/src/scripts/freezone.rhai
Normal file
@@ -0,0 +1,10 @@
|
||||
configure()
|
||||
.title("Zanzibar Digital Freezone")
|
||||
.description("Creating a better world.")
|
||||
.ws_url("wss://localhost:9000/ws")
|
||||
.logo("🌍")
|
||||
.save_circle();
|
||||
|
||||
let circle = get_configuration();
|
||||
|
||||
print("--- Creating OurWorld Library ---");
|
Reference in New Issue
Block a user