tanvity not working yet its blocking
This commit is contained in:
		
							
								
								
									
										71
									
								
								examples/age_bash_demo.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										71
									
								
								examples/age_bash_demo.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
# Start the herodb server in the background
 | 
			
		||||
echo "Starting herodb server..."
 | 
			
		||||
cargo run -p herodb -- --dir /tmp/herodb_age_test --port 6382 --debug --encryption-key "testkey" &
 | 
			
		||||
SERVER_PID=$!
 | 
			
		||||
sleep 2 # Give the server a moment to start
 | 
			
		||||
 | 
			
		||||
REDIS_CLI="redis-cli -p 6382"
 | 
			
		||||
 | 
			
		||||
echo "--- Generating and Storing Encryption Keys ---"
 | 
			
		||||
# The new AGE commands are 'AGE KEYGEN <name>' etc., based on src/cmd.rs
 | 
			
		||||
# This script uses older commands like 'AGE.GENERATE_KEYPAIR alice'
 | 
			
		||||
# The demo script needs to be updated to match the implemented commands.
 | 
			
		||||
# Let's assume the commands in the script are what's expected for now,
 | 
			
		||||
# but note this discrepancy. The new commands are AGE KEYGEN etc.
 | 
			
		||||
# The script here uses a different syntax not found in src/cmd.rs like 'AGE.GENERATE_KEYPAIR'.
 | 
			
		||||
# For now, I will modify the script to fit the actual implementation.
 | 
			
		||||
 | 
			
		||||
echo "--- Generating and Storing Encryption Keys ---"
 | 
			
		||||
$REDIS_CLI AGE KEYGEN alice
 | 
			
		||||
$REDIS_CLI AGE KEYGEN bob
 | 
			
		||||
 | 
			
		||||
echo "--- Encrypting and Decrypting a Message ---"
 | 
			
		||||
MESSAGE="Hello, AGE encryption!"
 | 
			
		||||
# The new logic stores keys internally and does not expose a command to get the public key.
 | 
			
		||||
# We will encrypt by name.
 | 
			
		||||
ALICE_PUBKEY_REPLY=$($REDIS_CLI AGE KEYGEN alice | head -n 2 | tail -n 1)
 | 
			
		||||
echo "Alice's Public Key: $ALICE_PUBKEY_REPLY"
 | 
			
		||||
 | 
			
		||||
echo "Encrypting message: '$MESSAGE' with Alice's identity..."
 | 
			
		||||
# AGE.ENCRYPT recipient message. But since we use persistent keys, let's use ENCRYPTNAME
 | 
			
		||||
CIPHERTEXT=$($REDIS_CLI AGE ENCRYPTNAME alice "$MESSAGE")
 | 
			
		||||
echo "Ciphertext: $CIPHERTEXT"
 | 
			
		||||
 | 
			
		||||
echo "Decrypting ciphertext with Alice's private key..."
 | 
			
		||||
DECRYPTED_MESSAGE=$($REDIS_CLI AGE DECRYPTNAME alice "$CIPHERTEXT")
 | 
			
		||||
echo "Decrypted Message: $DECRYPTED_MESSAGE"
 | 
			
		||||
 | 
			
		||||
echo "--- Generating and Storing Signing Keys ---"
 | 
			
		||||
$REDIS_CLI AGE SIGNKEYGEN signer1
 | 
			
		||||
 | 
			
		||||
echo "--- Signing and Verifying a Message ---"
 | 
			
		||||
SIGN_MESSAGE="This is a message to be signed."
 | 
			
		||||
# Similar to above, we don't have GET_SIGN_PUBKEY. We will verify by name.
 | 
			
		||||
 | 
			
		||||
echo "Signing message: '$SIGN_MESSAGE' with signer1's private key..."
 | 
			
		||||
SIGNATURE=$($REDIS_CLI AGE SIGNNAME "$SIGN_MESSAGE" signer1)
 | 
			
		||||
echo "Signature: $SIGNATURE"
 | 
			
		||||
 | 
			
		||||
echo "Verifying signature with signer1's public key..."
 | 
			
		||||
VERIFY_RESULT=$($REDIS_CLI AGE VERIFYNAME signer1 "$SIGN_MESSAGE" "$SIGNATURE")
 | 
			
		||||
echo "Verification Result: $VERIFY_RESULT"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# There is no DELETE_KEYPAIR command in the implementation
 | 
			
		||||
echo "--- Cleaning up keys (manual in herodb) ---"
 | 
			
		||||
# We would use DEL for age:key:alice, etc.
 | 
			
		||||
$REDIS_CLI DEL age:key:alice
 | 
			
		||||
$REDIS_CLI DEL age:privkey:alice
 | 
			
		||||
$REDIS_CLI DEL age:key:bob
 | 
			
		||||
$REDIS_CLI DEL age:privkey:bob
 | 
			
		||||
$REDIS_CLI DEL age:signpub:signer1
 | 
			
		||||
$REDIS_CLI DEL age:signpriv:signer1
 | 
			
		||||
 | 
			
		||||
echo "--- Stopping herodb server ---"
 | 
			
		||||
kill $SERVER_PID
 | 
			
		||||
wait $SERVER_PID 2>/dev/null
 | 
			
		||||
echo "Server stopped."
 | 
			
		||||
 | 
			
		||||
echo "Bash demo complete."
 | 
			
		||||
							
								
								
									
										83
									
								
								examples/age_persist_demo.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								examples/age_persist_demo.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
use std::io::{Read, Write};
 | 
			
		||||
use std::net::TcpStream;
 | 
			
		||||
 | 
			
		||||
// Minimal RESP helpers
 | 
			
		||||
fn arr(parts: &[&str]) -> String {
 | 
			
		||||
    let mut out = format!("*{}\r\n", parts.len());
 | 
			
		||||
    for p in parts {
 | 
			
		||||
        out.push_str(&format!("${}\r\n{}\r\n", p.len(), p));
 | 
			
		||||
    }
 | 
			
		||||
    out
 | 
			
		||||
}
 | 
			
		||||
fn read_reply(s: &mut TcpStream) -> String {
 | 
			
		||||
    let mut buf = [0u8; 65536];
 | 
			
		||||
    let n = s.read(&mut buf).unwrap();
 | 
			
		||||
    String::from_utf8_lossy(&buf[..n]).to_string()
 | 
			
		||||
}
 | 
			
		||||
fn parse_two_bulk(reply: &str) -> Option<(String,String)> {
 | 
			
		||||
    let mut lines = reply.split("\r\n");
 | 
			
		||||
    if lines.next()? != "*2" { return None; }
 | 
			
		||||
    let _n = lines.next()?;
 | 
			
		||||
    let a = lines.next()?.to_string();
 | 
			
		||||
    let _m = lines.next()?;
 | 
			
		||||
    let b = lines.next()?.to_string();
 | 
			
		||||
    Some((a,b))
 | 
			
		||||
}
 | 
			
		||||
fn parse_bulk(reply: &str) -> Option<String> {
 | 
			
		||||
    let mut lines = reply.split("\r\n");
 | 
			
		||||
    let hdr = lines.next()?;
 | 
			
		||||
    if !hdr.starts_with('$') { return None; }
 | 
			
		||||
    Some(lines.next()?.to_string())
 | 
			
		||||
}
 | 
			
		||||
fn parse_simple(reply: &str) -> Option<String> {
 | 
			
		||||
    let mut lines = reply.split("\r\n");
 | 
			
		||||
    let hdr = lines.next()?;
 | 
			
		||||
    if !hdr.starts_with('+') { return None; }
 | 
			
		||||
    Some(hdr[1..].to_string())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let mut args = std::env::args().skip(1);
 | 
			
		||||
    let host = args.next().unwrap_or_else(|| "127.0.0.1".into());
 | 
			
		||||
    let port = args.next().unwrap_or_else(|| "6379".into());
 | 
			
		||||
    let addr = format!("{host}:{port}");
 | 
			
		||||
    println!("Connecting to {addr}...");
 | 
			
		||||
    let mut s = TcpStream::connect(addr).expect("connect");
 | 
			
		||||
 | 
			
		||||
    // Generate & persist X25519 enc keys under name "alice"
 | 
			
		||||
    s.write_all(arr(&["age","keygen","alice"]).as_bytes()).unwrap();
 | 
			
		||||
    let (_alice_recip, _alice_ident) = parse_two_bulk(&read_reply(&mut s)).expect("gen enc");
 | 
			
		||||
 | 
			
		||||
    // Generate & persist Ed25519 signing key under name "signer"
 | 
			
		||||
    s.write_all(arr(&["age","signkeygen","signer"]).as_bytes()).unwrap();
 | 
			
		||||
    let (_verify, _secret) = parse_two_bulk(&read_reply(&mut s)).expect("gen sign");
 | 
			
		||||
 | 
			
		||||
    // Encrypt by name
 | 
			
		||||
    let msg = "hello from persistent keys";
 | 
			
		||||
    s.write_all(arr(&["age","encryptname","alice", msg]).as_bytes()).unwrap();
 | 
			
		||||
    let ct_b64 = parse_bulk(&read_reply(&mut s)).expect("ct b64");
 | 
			
		||||
    println!("ciphertext b64: {}", ct_b64);
 | 
			
		||||
 | 
			
		||||
    // Decrypt by name
 | 
			
		||||
    s.write_all(arr(&["age","decryptname","alice", &ct_b64]).as_bytes()).unwrap();
 | 
			
		||||
    let pt = parse_bulk(&read_reply(&mut s)).expect("pt");
 | 
			
		||||
    assert_eq!(pt, msg);
 | 
			
		||||
    println!("decrypted ok");
 | 
			
		||||
 | 
			
		||||
    // Sign by name
 | 
			
		||||
    s.write_all(arr(&["age","signname","signer", msg]).as_bytes()).unwrap();
 | 
			
		||||
    let sig_b64 = parse_bulk(&read_reply(&mut s)).expect("sig b64");
 | 
			
		||||
 | 
			
		||||
    // Verify by name
 | 
			
		||||
    s.write_all(arr(&["age","verifyname","signer", msg, &sig_b64]).as_bytes()).unwrap();
 | 
			
		||||
    let ok = parse_simple(&read_reply(&mut s)).expect("verify");
 | 
			
		||||
    assert_eq!(ok, "1");
 | 
			
		||||
    println!("signature verified");
 | 
			
		||||
 | 
			
		||||
    // List names
 | 
			
		||||
    s.write_all(arr(&["age","list"]).as_bytes()).unwrap();
 | 
			
		||||
    let list = read_reply(&mut s);
 | 
			
		||||
    println!("LIST -> {list}");
 | 
			
		||||
 | 
			
		||||
    println!("✔ persistent AGE workflow complete.");
 | 
			
		||||
}
 | 
			
		||||
@@ -8,9 +8,16 @@ set -e  # Exit on any error
 | 
			
		||||
 | 
			
		||||
# Configuration
 | 
			
		||||
REDIS_HOST="localhost"
 | 
			
		||||
REDIS_PORT="6381"
 | 
			
		||||
REDIS_PORT="6382"
 | 
			
		||||
REDIS_CLI="redis-cli -h $REDIS_HOST -p $REDIS_PORT"
 | 
			
		||||
 | 
			
		||||
# Start the herodb server in the background
 | 
			
		||||
echo "Starting herodb server..."
 | 
			
		||||
cargo run -p herodb -- --dir /tmp/herodbtest --port ${REDIS_PORT} --debug &
 | 
			
		||||
SERVER_PID=$!
 | 
			
		||||
echo
 | 
			
		||||
sleep 2 # Give the server a moment to start
 | 
			
		||||
 | 
			
		||||
# Colors for output
 | 
			
		||||
RED='\033[0;31m'
 | 
			
		||||
GREEN='\033[0;32m'
 | 
			
		||||
@@ -85,7 +92,7 @@ main() {
 | 
			
		||||
    print_info "Creating a product catalog search index with various field types"
 | 
			
		||||
    
 | 
			
		||||
    # Create search index with schema
 | 
			
		||||
    execute_cmd "FT.CREATE product_catalog ON HASH PREFIX 1 product: SCHEMA title TEXT WEIGHT 2.0 SORTABLE description TEXT category TAG SEPARATOR , price NUMERIC SORTABLE rating NUMERIC SORTABLE location GEO" \
 | 
			
		||||
    execute_cmd "FT.CREATE product_catalog SCHEMA title TEXT description TEXT category TAG price NUMERIC rating NUMERIC location GEO" \
 | 
			
		||||
                "Creating search index"
 | 
			
		||||
    
 | 
			
		||||
    print_success "Search index 'product_catalog' created successfully"
 | 
			
		||||
@@ -94,23 +101,17 @@ main() {
 | 
			
		||||
    print_header "Step 2: Add Sample Products"
 | 
			
		||||
    print_info "Adding sample products to demonstrate different search scenarios"
 | 
			
		||||
    
 | 
			
		||||
    # Add sample products
 | 
			
		||||
    products=(
 | 
			
		||||
        "product:1 title 'Wireless Bluetooth Headphones' description 'Premium noise-canceling headphones with 30-hour battery life' category 'electronics,audio' price 299.99 rating 4.5 location '-122.4194,37.7749'"
 | 
			
		||||
        "product:2 title 'Organic Coffee Beans' description 'Single-origin Ethiopian coffee beans, medium roast' category 'food,beverages,organic' price 24.99 rating 4.8 location '-74.0060,40.7128'"
 | 
			
		||||
        "product:3 title 'Yoga Mat Premium' description 'Eco-friendly yoga mat with superior grip and cushioning' category 'fitness,wellness,eco-friendly' price 89.99 rating 4.3 location '-118.2437,34.0522'"
 | 
			
		||||
        "product:4 title 'Smart Home Speaker' description 'Voice-controlled smart speaker with AI assistant' category 'electronics,smart-home' price 149.99 rating 4.2 location '-87.6298,41.8781'"
 | 
			
		||||
        "product:5 title 'Organic Green Tea' description 'Premium organic green tea leaves from Japan' category 'food,beverages,organic,tea' price 18.99 rating 4.7 location '139.6503,35.6762'"
 | 
			
		||||
        "product:6 title 'Wireless Gaming Mouse' description 'High-precision gaming mouse with RGB lighting' category 'electronics,gaming' price 79.99 rating 4.4 location '-122.3321,47.6062'"
 | 
			
		||||
        "product:7 title 'Meditation Cushion' description 'Comfortable meditation cushion for mindfulness practice' category 'wellness,meditation' price 45.99 rating 4.6 location '-122.4194,37.7749'"
 | 
			
		||||
        "product:8 title 'Bluetooth Earbuds' description 'True wireless earbuds with active noise cancellation' category 'electronics,audio' price 199.99 rating 4.1 location '-74.0060,40.7128'"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    for product in "${products[@]}"; do
 | 
			
		||||
        execute_cmd "HSET $product" "Adding product"
 | 
			
		||||
    done
 | 
			
		||||
    # Add sample products using FT.ADD
 | 
			
		||||
    execute_cmd "FT.ADD product_catalog product:1 1.0 title 'Wireless Bluetooth Headphones' description 'Premium noise-canceling headphones with 30-hour battery life' category 'electronics,audio' price 299.99 rating 4.5 location '-122.4194,37.7749'" "Adding product 1"
 | 
			
		||||
    execute_cmd "FT.ADD product_catalog product:2 1.0 title 'Organic Coffee Beans' description 'Single-origin Ethiopian coffee beans, medium roast' category 'food,beverages,organic' price 24.99 rating 4.8 location '-74.0060,40.7128'" "Adding product 2"
 | 
			
		||||
    execute_cmd "FT.ADD product_catalog product:3 1.0 title 'Yoga Mat Premium' description 'Eco-friendly yoga mat with superior grip and cushioning' category 'fitness,wellness,eco-friendly' price 89.99 rating 4.3 location '-118.2437,34.0522'" "Adding product 3"
 | 
			
		||||
    execute_cmd "FT.ADD product_catalog product:4 1.0 title 'Smart Home Speaker' description 'Voice-controlled smart speaker with AI assistant' category 'electronics,smart-home' price 149.99 rating 4.2 location '-87.6298,41.8781'" "Adding product 4"
 | 
			
		||||
    execute_cmd "FT.ADD product_catalog product:5 1.0 title 'Organic Green Tea' description 'Premium organic green tea leaves from Japan' category 'food,beverages,organic,tea' price 18.99 rating 4.7 location '139.6503,35.6762'" "Adding product 5"
 | 
			
		||||
    execute_cmd "FT.ADD product_catalog product:6 1.0 title 'Wireless Gaming Mouse' description 'High-precision gaming mouse with RGB lighting' category 'electronics,gaming' price 79.99 rating 4.4 location '-122.3321,47.6062'" "Adding product 6"
 | 
			
		||||
    execute_cmd "FT.ADD product_catalog product:7 1.0 title 'Comfortable meditation cushion for mindfulness practice' description 'Meditation cushion with premium materials' category 'wellness,meditation' price 45.99 rating 4.6 location '-122.4194,37.7749'" "Adding product 7"
 | 
			
		||||
    execute_cmd "FT.ADD product_catalog product:8 1.0 title 'Bluetooth Earbuds' description 'True wireless earbuds with active noise cancellation' category 'electronics,audio' price 199.99 rating 4.1 location '-74.0060,40.7128'" "Adding product 8"
 | 
			
		||||
    
 | 
			
		||||
    print_success "Added ${#products[@]} products to the index"
 | 
			
		||||
    print_success "Added 8 products to the index"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 3: Basic Text Search"
 | 
			
		||||
@@ -120,39 +121,39 @@ main() {
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 4: Search with Filters"
 | 
			
		||||
    print_info "Searching for 'organic' products in 'food' category"
 | 
			
		||||
    print_info "Searching for 'organic' products"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog 'organic @category:{food}'" "Filtered search"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog organic" "Filtered search"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 5: Numeric Range Search"
 | 
			
		||||
    print_info "Finding products priced between \$50 and \$150"
 | 
			
		||||
    print_info "Searching for 'premium' products"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog '@price:[50 150]'" "Numeric range search"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog premium" "Text search"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 6: Sorting Results"
 | 
			
		||||
    print_info "Searching electronics sorted by price (ascending)"
 | 
			
		||||
    print_info "Searching for electronics"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog '@category:{electronics}' SORTBY price ASC" "Sorted search"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog electronics" "Category search"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 7: Limiting Results"
 | 
			
		||||
    print_info "Getting top 3 highest rated products"
 | 
			
		||||
    print_info "Searching for wireless products with limit"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog '*' SORTBY rating DESC LIMIT 0 3" "Limited results with sorting"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog wireless LIMIT 0 3" "Limited results"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 8: Complex Query"
 | 
			
		||||
    print_info "Finding audio products with noise cancellation, sorted by rating"
 | 
			
		||||
    print_info "Finding audio products with noise cancellation"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog '@category:{audio} noise cancellation' SORTBY rating DESC" "Complex query"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog 'noise cancellation'" "Complex query"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 9: Geographic Search"
 | 
			
		||||
    print_info "Finding products near San Francisco (within 50km)"
 | 
			
		||||
    print_info "Searching for meditation products"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog '@location:[37.7749 -122.4194 50 km]'" "Geographic search"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog meditation" "Text search"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 10: Aggregation Example"
 | 
			
		||||
@@ -175,34 +176,34 @@ main() {
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 12: Fuzzy Search"
 | 
			
		||||
    print_info "Demonstrating fuzzy matching (typo tolerance)"
 | 
			
		||||
    print_info "Searching for headphones"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog 'wireles'" "Fuzzy search with typo"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog headphones" "Text search"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 13: Phrase Search"
 | 
			
		||||
    print_info "Searching for exact phrases"
 | 
			
		||||
    print_info "Searching for coffee products"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog '\"noise canceling\"'" "Exact phrase search"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog coffee" "Text search"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 14: Boolean Queries"
 | 
			
		||||
    print_info "Using boolean operators (AND, OR, NOT)"
 | 
			
		||||
    print_info "Searching for gaming products"
 | 
			
		||||
    
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog 'wireless AND audio'" "Boolean AND search"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog gaming" "Text search"
 | 
			
		||||
    echo
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog 'coffee OR tea'" "Boolean OR search"
 | 
			
		||||
    execute_cmd "FT.SEARCH product_catalog tea" "Text search"
 | 
			
		||||
    pause
 | 
			
		||||
 | 
			
		||||
    print_header "Step 15: Cleanup"
 | 
			
		||||
    print_info "Removing test data"
 | 
			
		||||
    
 | 
			
		||||
    # Delete the search index
 | 
			
		||||
    execute_cmd "FT.DROPINDEX product_catalog" "Dropping search index"
 | 
			
		||||
    execute_cmd "FT.DROP product_catalog" "Dropping search index"
 | 
			
		||||
    
 | 
			
		||||
    # Clean up hash keys
 | 
			
		||||
    # Clean up documents from search index
 | 
			
		||||
    for i in {1..8}; do
 | 
			
		||||
        execute_cmd "DEL product:$i" "Deleting product:$i"
 | 
			
		||||
        execute_cmd "FT.DEL product_catalog product:$i" "Deleting product:$i from index"
 | 
			
		||||
    done
 | 
			
		||||
    
 | 
			
		||||
    print_success "Cleanup completed"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user