feat: reorganize examples and add signature support to JobBuilder
- Reorganized examples into osiris/, sal/, and utils/ folders - Moved hardcoded scripts to separate .rhai files - Added signature() method to JobBuilder for job signing - Updated OSIRIS context to use block_in_place instead of runtime - Removed runtime field from OsirisContext - Added typed save() methods for Note and Event objects - Updated all examples to use new structure and APIs
This commit is contained in:
54
examples/README.md
Normal file
54
examples/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Runner Examples
|
||||
|
||||
This directory contains organized examples demonstrating different aspects of the runner system.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
examples/
|
||||
├── osiris/ # OSIRIS context and object management examples
|
||||
├── sal/ # System Abstraction Layer (SAL) DSL examples
|
||||
└── utils/ # Utility examples (signing, crypto, etc.)
|
||||
```
|
||||
|
||||
## Running Examples
|
||||
|
||||
### OSIRIS Example
|
||||
Complete example demonstrating OSIRIS context management, Note and Event creation, and access control:
|
||||
|
||||
```bash
|
||||
cargo run --example osiris
|
||||
```
|
||||
|
||||
See [osiris/README.md](osiris/README.md) for details.
|
||||
|
||||
### SAL Example
|
||||
Examples demonstrating various SAL DSL modules for system operations:
|
||||
|
||||
```bash
|
||||
cargo run --example sal
|
||||
```
|
||||
|
||||
See [sal/README.md](sal/README.md) for details.
|
||||
|
||||
### Utility Examples
|
||||
Utility examples for cryptographic operations and job signing:
|
||||
|
||||
```bash
|
||||
cargo run --example sign_job --features crypto
|
||||
```
|
||||
|
||||
See [utils/README.md](utils/README.md) for details.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Redis server running on `localhost:6379`
|
||||
- For OSIRIS examples: HeroDB instance (or uses local SQLite)
|
||||
- For crypto examples: Enable the `crypto` feature flag
|
||||
|
||||
## Example Structure
|
||||
|
||||
Each example folder contains:
|
||||
- `main.rs` - The main Rust example code
|
||||
- `*.rhai` - Rhai script files demonstrating various features
|
||||
- `README.md` - Detailed documentation for that example category
|
||||
175
examples/osiris/README.md
Normal file
175
examples/osiris/README.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# OSIRIS Complete Example
|
||||
|
||||
A comprehensive end-to-end example demonstrating the complete OSIRIS workflow.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Redis** - Must be running on localhost:6379
|
||||
```bash
|
||||
redis-server
|
||||
```
|
||||
|
||||
2. **Rust** - Version 1.88+
|
||||
```bash
|
||||
rustup update
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
### osiris_complete - Full End-to-End Workflow
|
||||
|
||||
**ONE EXAMPLE TO RULE THEM ALL** - Complete demonstration of OSIRIS.
|
||||
|
||||
**Run:**
|
||||
```bash
|
||||
cd /Users/timurgordon/code/git.ourworld.tf/herocode/runner_rust
|
||||
cargo run --example osiris_complete
|
||||
```
|
||||
|
||||
**What it demonstrates:**
|
||||
1. **Runner Management** - Starts and stops runner_osiris daemon
|
||||
2. **Job Client** - Creates client with builder pattern
|
||||
3. **Job Building** - Uses JobBuilder for clean job creation
|
||||
4. **Synchronous Execution** - Uses `run_job()` to wait for results
|
||||
5. **OSIRIS Objects** - Creates Note and Event objects
|
||||
6. **Context Storage** - Stores objects in participant-based contexts
|
||||
7. **Data Querying** - Retrieves and lists stored data
|
||||
8. **Access Control** - Demonstrates signatory-based access
|
||||
9. **Error Handling** - Proper error propagation and cleanup
|
||||
|
||||
**Expected Output:**
|
||||
```
|
||||
🚀 OSIRIS Demo Script
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Step 1: Getting context for participants [alice, bob]
|
||||
✓ Context ID: alice,bob
|
||||
|
||||
Step 2: Creating a Note
|
||||
✓ Note created with title: Project Planning Meeting
|
||||
...
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Context Management
|
||||
|
||||
**Simple Logic:**
|
||||
- Context = list of public keys (participants)
|
||||
- To get_context, at least one participant must be a signatory
|
||||
- No state tracking - contexts created fresh each time
|
||||
|
||||
**Example:**
|
||||
```rhai
|
||||
// Signatories: [alice, bob, charlie]
|
||||
|
||||
// ✅ Works - alice is a signatory
|
||||
let ctx = get_context(["alice", "bob"]);
|
||||
|
||||
// ❌ Fails - dave is not a signatory
|
||||
let ctx = get_context(["alice", "dave"]);
|
||||
```
|
||||
|
||||
### OSIRIS Objects
|
||||
|
||||
**Note:**
|
||||
```rhai
|
||||
let note = note("collection_name")
|
||||
.title("My Note")
|
||||
.content("Note content")
|
||||
.tag("key", "value")
|
||||
.mime("text/plain");
|
||||
```
|
||||
|
||||
**Event:**
|
||||
```rhai
|
||||
let event = event("collection_name")
|
||||
.title("My Event")
|
||||
.description("Event description")
|
||||
.location("Location")
|
||||
.tag("type", "meeting");
|
||||
```
|
||||
|
||||
### Context Operations
|
||||
|
||||
**Save:**
|
||||
```rhai
|
||||
let id = ctx.save("collection", "object_id", object);
|
||||
```
|
||||
|
||||
**Get:**
|
||||
```rhai
|
||||
let obj = ctx.get("collection", "object_id");
|
||||
```
|
||||
|
||||
**List:**
|
||||
```rhai
|
||||
let ids = ctx.list("collection");
|
||||
```
|
||||
|
||||
**Delete:**
|
||||
```rhai
|
||||
let deleted = ctx.delete("collection", "object_id");
|
||||
```
|
||||
|
||||
**Query:**
|
||||
```rhai
|
||||
let results = ctx.query("collection", "field", "value");
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ Rhai Script │
|
||||
│ (osiris_demo.rhai)│
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ OSIRIS Engine │
|
||||
│ - Note API │
|
||||
│ - Event API │
|
||||
│ - get_context() │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ OsirisContext │
|
||||
│ - Participants │
|
||||
│ - CRUD operations │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ HeroDB │
|
||||
│ (Redis + local DB) │
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Connection refused" on port 6379
|
||||
- Make sure Redis is running: `redis-server`
|
||||
- Check: `redis-cli ping` (should return "PONG")
|
||||
|
||||
### "Access denied: none of the participants are signatories"
|
||||
- Check that at least one participant is in the SIGNATORIES list
|
||||
- Signatories are set via engine tags (see examples)
|
||||
|
||||
### "Failed to create context"
|
||||
- Verify Redis is accessible
|
||||
- Check HeroDB URL is correct
|
||||
- Ensure db_id is valid (typically 1)
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Modify the scripts** - Edit `osiris_demo.rhai` to try different operations
|
||||
2. **Add more objects** - Create your own object types
|
||||
3. **Multi-context** - Try creating multiple contexts with different participants
|
||||
4. **Integration** - Use OSIRIS in your own applications
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ Ready to Use
|
||||
**Last Updated:** 2025-10-24
|
||||
8
examples/osiris/access_denied.rhai
Normal file
8
examples/osiris/access_denied.rhai
Normal file
@@ -0,0 +1,8 @@
|
||||
print("Attempting to access context with non-signatories...");
|
||||
print("Participants: [dave, eve]");
|
||||
print("Signatories: [alice, bob, charlie]");
|
||||
|
||||
// This should fail because neither dave nor eve are signatories
|
||||
let ctx = get_context(["dave", "eve"]);
|
||||
|
||||
"This should not succeed!"
|
||||
18
examples/osiris/event.rhai
Normal file
18
examples/osiris/event.rhai
Normal file
@@ -0,0 +1,18 @@
|
||||
print("Creating context for [alice, bob]...");
|
||||
let ctx = get_context(["alice", "bob"]);
|
||||
print("✓ Context ID: " + ctx.context_id());
|
||||
|
||||
print("\nCreating event...");
|
||||
let event = event("events")
|
||||
.title("Team Retrospective")
|
||||
.description("Review what went well and areas for improvement")
|
||||
.location("Virtual - Zoom Room A")
|
||||
.category("retrospective");
|
||||
|
||||
print("✓ Event created");
|
||||
|
||||
print("\nStoring event in context...");
|
||||
ctx.save(event);
|
||||
print("✓ Event stored");
|
||||
|
||||
"Event 'Team Retrospective' created and stored successfully"
|
||||
248
examples/osiris/main.rs
Normal file
248
examples/osiris/main.rs
Normal file
@@ -0,0 +1,248 @@
|
||||
/// Complete End-to-End OSIRIS Example
|
||||
///
|
||||
/// This example demonstrates the complete OSIRIS workflow:
|
||||
/// 1. Starting the runner_osiris daemon
|
||||
/// 2. Creating jobs with JobBuilder
|
||||
/// 3. Running jobs with run_job() (synchronous)
|
||||
/// 4. Creating OSIRIS objects (Note, Event)
|
||||
/// 5. Storing objects in contexts
|
||||
/// 6. Querying and retrieving data
|
||||
/// 7. Proper cleanup
|
||||
///
|
||||
/// Prerequisites:
|
||||
/// - Redis running on localhost:6379
|
||||
///
|
||||
/// Run with:
|
||||
/// ```bash
|
||||
/// cargo run --example osiris_complete
|
||||
/// ```
|
||||
|
||||
use runner_rust::job::{JobBuilder, Client};
|
||||
use std::time::Duration;
|
||||
use tokio::process::Command;
|
||||
use tokio::time::sleep;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("🚀 OSIRIS Complete End-to-End Example");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
// ========================================================================
|
||||
// STEP 1: Start the runner daemon
|
||||
// ========================================================================
|
||||
println!("Step 1: Starting runner_osiris daemon");
|
||||
println!("─────────────────────────────────────────────────────────────\n");
|
||||
|
||||
let mut runner = Command::new("cargo")
|
||||
.args(&[
|
||||
"run",
|
||||
"--bin",
|
||||
"runner_osiris",
|
||||
"--",
|
||||
"demo_runner",
|
||||
"--db-path",
|
||||
"/tmp/osiris_complete.db",
|
||||
"--redis-url",
|
||||
"redis://localhost:6379",
|
||||
])
|
||||
.spawn()?;
|
||||
|
||||
println!("✓ Runner started (PID: {})", runner.id().unwrap_or(0));
|
||||
println!(" Runner ID: demo_runner");
|
||||
println!(" Queue: demo_runner");
|
||||
println!(" DB: /tmp/osiris_complete.db");
|
||||
|
||||
// Give the runner time to initialize
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
println!("\n");
|
||||
|
||||
// ========================================================================
|
||||
// STEP 2: Create job client
|
||||
// ========================================================================
|
||||
println!("Step 2: Creating job client");
|
||||
println!("─────────────────────────────────────────────────────────────\n");
|
||||
|
||||
let client = Client::builder()
|
||||
.redis_url("redis://localhost:6379")
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
println!("✓ Job client created\n");
|
||||
|
||||
// ========================================================================
|
||||
// STEP 3: Create and store a Note
|
||||
// ========================================================================
|
||||
println!("Step 3: Creating and Storing a Note");
|
||||
println!("─────────────────────────────────────────────────────────────\n");
|
||||
|
||||
let create_note_script = std::fs::read_to_string("examples/osiris/note.rhai")?;
|
||||
|
||||
let job1 = JobBuilder::new()
|
||||
.caller_id("example_client")
|
||||
.context_id("demo_context")
|
||||
.payload(create_note_script)
|
||||
.runner("demo_runner")
|
||||
.executor("rhai")
|
||||
.timeout(30)
|
||||
.signature("alice", "")
|
||||
.signature("bob", "")
|
||||
.signature("charlie", "")
|
||||
.build()?;
|
||||
|
||||
println!("Running job: Create Note");
|
||||
println!("Job ID: {}", job1.id);
|
||||
|
||||
match client.run_job(&job1, "demo_runner", 60).await {
|
||||
Ok(result) => {
|
||||
println!("\n✅ {}\n", result);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("\n❌ Job failed: {}\n", e);
|
||||
let _ = runner.kill().await;
|
||||
return Err(format!("Job failed: {}", e).into());
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// STEP 4: Create and store an Event
|
||||
// ========================================================================
|
||||
println!("Step 4: Creating and Storing an Event");
|
||||
println!("─────────────────────────────────────────────────────────────\n");
|
||||
|
||||
let create_event_script = std::fs::read_to_string("examples/osiris/event.rhai")?;
|
||||
|
||||
let job2 = JobBuilder::new()
|
||||
.caller_id("example_client")
|
||||
.context_id("demo_context")
|
||||
.payload(create_event_script)
|
||||
.runner("demo_runner")
|
||||
.executor("rhai")
|
||||
.timeout(30)
|
||||
.signature("alice", "")
|
||||
.signature("bob", "")
|
||||
.signature("charlie", "")
|
||||
.build()?;
|
||||
|
||||
println!("Running job: Create Event");
|
||||
println!("Job ID: {}", job2.id);
|
||||
|
||||
match client.run_job(&job2, "demo_runner", 60).await {
|
||||
Ok(result) => {
|
||||
println!("\n✅ {}\n", result);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("\n❌ Job failed: {}\n", e);
|
||||
let _ = runner.kill().await;
|
||||
return Err(format!("Job failed: {}", e).into());
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// STEP 5: Query context data
|
||||
// ========================================================================
|
||||
println!("Step 5: Querying Context Data");
|
||||
println!("─────────────────────────────────────────────────────────────\n");
|
||||
|
||||
let query_script = std::fs::read_to_string("examples/osiris/query.rhai")?;
|
||||
|
||||
let job3 = JobBuilder::new()
|
||||
.caller_id("example_client")
|
||||
.context_id("demo_context")
|
||||
.payload(query_script)
|
||||
.runner("demo_runner")
|
||||
.executor("rhai")
|
||||
.timeout(30)
|
||||
.signature("alice", "")
|
||||
.signature("bob", "")
|
||||
.signature("charlie", "")
|
||||
.build()?;
|
||||
|
||||
println!("Running job: Query Data");
|
||||
println!("Job ID: {}", job3.id);
|
||||
|
||||
match client.run_job(&job3, "demo_runner", 60).await {
|
||||
Ok(result) => {
|
||||
println!("\n✅ {}\n", result);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("\n❌ Job failed: {}\n", e);
|
||||
let _ = runner.kill().await;
|
||||
return Err(format!("Job failed: {}", e).into());
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// STEP 6: Demonstrate access control
|
||||
// ========================================================================
|
||||
println!("Step 6: Testing Access Control");
|
||||
println!("─────────────────────────────────────────────────────────────\n");
|
||||
|
||||
let access_denied_script = std::fs::read_to_string("examples/osiris/access_denied.rhai")?;
|
||||
|
||||
let job4 = JobBuilder::new()
|
||||
.caller_id("example_client")
|
||||
.context_id("demo_context")
|
||||
.payload(access_denied_script)
|
||||
.runner("demo_runner")
|
||||
.executor("rhai")
|
||||
.timeout(30)
|
||||
.signature("alice", "")
|
||||
.signature("bob", "")
|
||||
.signature("charlie", "")
|
||||
.build()?;
|
||||
|
||||
println!("Running job: Access Control Test");
|
||||
println!("Job ID: {}", job4.id);
|
||||
println!("Expected: Access denied\n");
|
||||
|
||||
match client.run_job(&job4, "demo_runner", 60).await {
|
||||
Ok(result) => {
|
||||
println!("❌ Unexpected success: {}\n", result);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✅ Access denied as expected");
|
||||
println!(" Error: {}\n", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// STEP 7: Cleanup
|
||||
// ========================================================================
|
||||
println!("Step 7: Cleanup");
|
||||
println!("─────────────────────────────────────────────────────────────\n");
|
||||
|
||||
println!("Stopping runner...");
|
||||
runner.kill().await?;
|
||||
println!("✓ Runner stopped\n");
|
||||
|
||||
// ========================================================================
|
||||
// Summary
|
||||
// ========================================================================
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
println!("🎉 Complete Example Finished!\n");
|
||||
println!("📝 What We Demonstrated:");
|
||||
println!(" ✓ Started runner_osiris daemon");
|
||||
println!(" ✓ Created job client with builder pattern");
|
||||
println!(" ✓ Built jobs with JobBuilder");
|
||||
println!(" ✓ Used run_job() for synchronous execution");
|
||||
println!(" ✓ Created OSIRIS Note object");
|
||||
println!(" ✓ Created OSIRIS Event object");
|
||||
println!(" ✓ Stored objects in contexts");
|
||||
println!(" ✓ Queried and retrieved data");
|
||||
println!(" ✓ Demonstrated participant-based access control");
|
||||
println!(" ✓ Proper cleanup and shutdown");
|
||||
println!("\n🏗️ Architecture:");
|
||||
println!(" • Contexts defined by participant public keys");
|
||||
println!(" • At least one participant must be a signatory");
|
||||
println!(" • No state tracking - contexts created on demand");
|
||||
println!(" • Jobs executed via Redis queue");
|
||||
println!(" • Results returned synchronously");
|
||||
println!("\n💡 Key Features:");
|
||||
println!(" • Simple API: client.run_job()");
|
||||
println!(" • Fluent builders: JobBuilder, note(), event()");
|
||||
println!(" • Automatic waiting and result extraction");
|
||||
println!(" • Proper error handling and timeouts");
|
||||
println!(" • Production-ready job infrastructure");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
20
examples/osiris/note.rhai
Normal file
20
examples/osiris/note.rhai
Normal file
@@ -0,0 +1,20 @@
|
||||
print("Creating context for [alice, bob]...");
|
||||
let ctx = get_context(["alice", "bob"]);
|
||||
print("✓ Context ID: " + ctx.context_id());
|
||||
|
||||
print("\nCreating note...");
|
||||
let note = note("notes")
|
||||
.title("Sprint Planning Meeting")
|
||||
.content("Discussed Q1 2025 roadmap and milestones")
|
||||
.tag("sprint", "2025-Q1")
|
||||
.tag("team", "engineering")
|
||||
.tag("priority", "high")
|
||||
.mime("text/markdown");
|
||||
|
||||
print("✓ Note created");
|
||||
|
||||
print("\nStoring note in context...");
|
||||
ctx.save(note);
|
||||
print("✓ Note stored");
|
||||
|
||||
"Note 'Sprint Planning Meeting' created and stored successfully"
|
||||
21
examples/osiris/query.rhai
Normal file
21
examples/osiris/query.rhai
Normal file
@@ -0,0 +1,21 @@
|
||||
print("Querying context [alice, bob]...");
|
||||
let ctx = get_context(["alice", "bob"]);
|
||||
print("✓ Context ID: " + ctx.context_id());
|
||||
|
||||
print("\nListing all notes...");
|
||||
let notes = ctx.list("notes");
|
||||
print("✓ Found " + notes.len() + " note(s)");
|
||||
|
||||
print("\nRetrieving specific note...");
|
||||
let note = ctx.get("notes", "sprint_planning_001");
|
||||
print("✓ Retrieved note: sprint_planning_001");
|
||||
|
||||
print("\nQuerying context [alice, bob, charlie]...");
|
||||
let ctx2 = get_context(["alice", "bob", "charlie"]);
|
||||
print("✓ Context ID: " + ctx2.context_id());
|
||||
|
||||
print("\nListing all events...");
|
||||
let events = ctx2.list("events");
|
||||
print("✓ Found " + events.len() + " event(s)");
|
||||
|
||||
"Query complete: Found " + notes.len() + " notes and " + events.len() + " events"
|
||||
@@ -1,37 +0,0 @@
|
||||
/// Example: Running OSIRIS Rhai scripts
|
||||
///
|
||||
/// This example demonstrates how to use the OSIRIS Rhai engine
|
||||
/// to execute scripts that create and manipulate OSIRIS objects.
|
||||
///
|
||||
/// Prerequisites:
|
||||
/// - HeroDB running on localhost:6379
|
||||
/// - osiris crate added as dependency with rhai-support feature
|
||||
///
|
||||
/// Run with:
|
||||
/// ```bash
|
||||
/// cargo run --example osiris_example
|
||||
/// ```
|
||||
|
||||
use runner_rust::engine::osiris::run_osiris_script;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("🚀 OSIRIS Rhai Engine Example\n");
|
||||
|
||||
// Example 1: Inline script
|
||||
println!("Example 1: Inline Script");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
let script = r#"
|
||||
print("Creating a note from inline script...");
|
||||
let note = note("notes");
|
||||
print(note);
|
||||
"#;
|
||||
|
||||
run_osiris_script(script, "redis://localhost:6379", 1)?;
|
||||
|
||||
println!("\n✅ Example completed!");
|
||||
println!("\nNote: Full OSIRIS integration requires adding osiris crate");
|
||||
println!(" as a dependency with the 'rhai-support' feature enabled.");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
// OSIRIS Rhai Script Example
|
||||
// This script demonstrates creating and storing OSIRIS objects
|
||||
|
||||
print("=== OSIRIS Rhai Script Example ===\n");
|
||||
|
||||
// Create a note with fluent builder pattern
|
||||
print("Creating a note...");
|
||||
let note = note("notes")
|
||||
.title("My First Rhai Note")
|
||||
.content("This note was created from a Rhai script using the OSIRIS engine!")
|
||||
.tag("source", "rhai")
|
||||
.tag("project", "osiris")
|
||||
.tag("priority", "high")
|
||||
.mime("text/plain");
|
||||
|
||||
print(`Note created: ${note.get_title()}`);
|
||||
|
||||
// Store the note in HeroDB
|
||||
print("Storing note...");
|
||||
let note_id = put_note(note);
|
||||
print(`✓ Note stored with ID: ${note_id}\n`);
|
||||
|
||||
// Retrieve the note
|
||||
print("Retrieving note...");
|
||||
let retrieved_note = get_note("notes", note_id);
|
||||
print(`✓ Retrieved: ${retrieved_note.get_title()}`);
|
||||
print(` Content: ${retrieved_note.get_content()}\n`);
|
||||
|
||||
// Create an event
|
||||
print("Creating an event...");
|
||||
let event = event("calendar", "Team Meeting")
|
||||
.description("Weekly team sync")
|
||||
.location("Conference Room A")
|
||||
.category("meetings")
|
||||
.all_day(false);
|
||||
|
||||
print(`Event created: ${event.get_title()}`);
|
||||
|
||||
// Store the event
|
||||
print("Storing event...");
|
||||
let event_id = put_event(event);
|
||||
print(`✓ Event stored with ID: ${event_id}\n`);
|
||||
|
||||
// Query notes by tag
|
||||
print("Querying notes by tag (project=osiris)...");
|
||||
let ids = query("notes", "tags:tag", "project=osiris");
|
||||
print(`✓ Found ${ids.len()} note(s) with tag project=osiris`);
|
||||
|
||||
for id in ids {
|
||||
let n = get_note("notes", id);
|
||||
print(` - ${n.get_title()}`);
|
||||
}
|
||||
|
||||
print("\n=== Script completed successfully! ===");
|
||||
64
examples/sal/README.md
Normal file
64
examples/sal/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# SAL (System Abstraction Layer) Examples
|
||||
|
||||
This directory contains examples demonstrating the SAL DSL modules for system operations.
|
||||
|
||||
## Running the Example
|
||||
|
||||
```bash
|
||||
cargo run --example sal
|
||||
```
|
||||
|
||||
## Available Scripts
|
||||
|
||||
The `scripts/` directory contains various Rhai scripts demonstrating different SAL modules:
|
||||
|
||||
### Basics
|
||||
- `basics/` - Basic Rhai language features and syntax
|
||||
|
||||
### Containers
|
||||
- `containers/` - Container management operations
|
||||
|
||||
### Git
|
||||
- `git/` - Git repository operations
|
||||
|
||||
### Hero Vault
|
||||
- `hero_vault/` - Secure credential storage and retrieval
|
||||
|
||||
### Kubernetes
|
||||
- `kubernetes/` - Kubernetes cluster management
|
||||
|
||||
### Mycelium
|
||||
- `mycelium/` - Mycelium network operations
|
||||
|
||||
### Network
|
||||
- `network/` - Network utilities and operations
|
||||
|
||||
### PostgreSQL
|
||||
- `postgresclient/` - PostgreSQL database operations
|
||||
|
||||
### Process
|
||||
- `process/` - Process management and execution
|
||||
|
||||
### Redis
|
||||
- `redisclient/` - Redis operations
|
||||
|
||||
### Service Manager
|
||||
- `service_manager/` - System service management
|
||||
|
||||
### Zinit
|
||||
- `zinit/` - Zinit service manager operations
|
||||
|
||||
## Script Structure
|
||||
|
||||
Each script demonstrates:
|
||||
- Module initialization
|
||||
- Common operations
|
||||
- Error handling
|
||||
- Best practices
|
||||
|
||||
## Configuration
|
||||
|
||||
The example uses:
|
||||
- Default database path: `/tmp/sal_engine.db`
|
||||
- Context isolation per script
|
||||
- Verbose output for debugging
|
||||
@@ -1,46 +0,0 @@
|
||||
/// Quick test of OSIRIS Rhai integration
|
||||
///
|
||||
/// Run with:
|
||||
/// ```bash
|
||||
/// cargo run --example test_osiris
|
||||
/// ```
|
||||
|
||||
use runner_rust::engine::osiris::create_osiris_engine;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("🧪 Testing OSIRIS Rhai Engine\n");
|
||||
|
||||
// Test 1: Create engine
|
||||
println!("Test 1: Creating OSIRIS engine...");
|
||||
let engine = create_osiris_engine("redis://localhost:6379", 1)?;
|
||||
println!("✓ Engine created successfully\n");
|
||||
|
||||
// Test 2: Run simple script
|
||||
println!("Test 2: Running simple script...");
|
||||
let script = r#"
|
||||
print("Hello from OSIRIS Rhai!");
|
||||
|
||||
// Create a note
|
||||
let note = note("test_notes")
|
||||
.title("Test Note")
|
||||
.content("This is a test")
|
||||
.tag("test", "true");
|
||||
|
||||
print("Note created: " + note.get_title());
|
||||
"#;
|
||||
|
||||
match engine.eval::<()>(script) {
|
||||
Ok(_) => println!("✓ Script executed successfully\n"),
|
||||
Err(e) => {
|
||||
println!("✗ Script error: {}\n", e);
|
||||
println!("Note: This is expected if HeroDB is not running");
|
||||
}
|
||||
}
|
||||
|
||||
println!("✅ Tests completed!");
|
||||
println!("\nTo run full integration:");
|
||||
println!("1. Start HeroDB: cd ../herodb && cargo run --release");
|
||||
println!("2. Run: cargo run --example test_osiris");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
20
examples/utils/README.md
Normal file
20
examples/utils/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Utility Examples
|
||||
|
||||
This directory contains utility examples for working with the runner system.
|
||||
|
||||
## sign_job
|
||||
|
||||
Demonstrates how to:
|
||||
- Create a job with signatories
|
||||
- Sign the job with secp256k1 private keys
|
||||
- Verify the signatures
|
||||
|
||||
### Usage
|
||||
|
||||
```bash
|
||||
cargo run --example sign_job --features crypto
|
||||
```
|
||||
|
||||
### Requirements
|
||||
|
||||
The `crypto` feature must be enabled to use cryptographic signing functionality.
|
||||
Reference in New Issue
Block a user