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