terraphim_middleware 1.16.33

Terraphim middleware for searching haystacks
Documentation
use serde_json::json;
use std::collections::HashMap;
use terraphim_atomic_client::{self, Store};
use terraphim_config::Haystack;
use terraphim_middleware::{haystack::AtomicHaystackIndexer, indexer::IndexMiddleware};
use uuid::Uuid;

#[tokio::test]
#[ignore]
async fn test_atomic_haystack_indexer() {
    // This test requires a running Atomic Server instance and a .env file
    // at the root of the workspace with the following content:
    // ATOMIC_SERVER_URL=http://localhost:9883
    // ATOMIC_SERVER_SECRET=...
    dotenvy::dotenv().ok();

    let config =
        terraphim_atomic_client::Config::from_env().expect("Failed to load config from env");
    let store = Store::new(config.clone()).expect("Failed to create store");

    // 1. Create a parent resource for the test articles
    let server_url = config.server_url.trim_end_matches('/');
    let parent_subject = format!("{}/test/articles", server_url);
    let mut parent_properties = HashMap::new();
    parent_properties.insert(
        "https://atomicdata.dev/properties/isA".to_string(),
        json!(["https://atomicdata.dev/classes/Collection"]),
    );
    parent_properties.insert(
        "https://atomicdata.dev/properties/name".to_string(),
        json!("Test Articles"),
    );
    parent_properties.insert(
        "https://atomicdata.dev/properties/parent".to_string(),
        json!(server_url),
    );
    store
        .create_with_commit(&parent_subject, parent_properties)
        .await
        .unwrap();

    // 2. Create some test articles on the server
    let article1_subject = format!("{}/test/article/{}", server_url, Uuid::new_v4());
    let mut properties1 = HashMap::new();
    properties1.insert(
        "https://atomicdata.dev/properties/isA".to_string(),
        json!(["https://atomicdata.dev/classes/Article"]),
    );
    properties1.insert(
        "https://atomicdata.dev/properties/name".to_string(),
        json!("Test Article 1: The Magic of Rust"),
    );
    properties1.insert(
        "https://atomicdata.dev/properties/description".to_string(),
        json!("A deep dive into Rust's ownership model and concurrency features."),
    );
    properties1.insert(
        "https://atomicdata.dev/properties/parent".to_string(),
        json!(parent_subject),
    );

    store
        .create_with_commit(&article1_subject, properties1)
        .await
        .unwrap();

    let article2_subject = format!("{}/test/article/{}", server_url, Uuid::new_v4());
    let mut properties2 = HashMap::new();
    properties2.insert(
        "https://atomicdata.dev/properties/isA".to_string(),
        json!(["https://atomicdata.dev/classes/Article"]),
    );
    properties2.insert(
        "https://atomicdata.dev/properties/name".to_string(),
        json!("Test Article 2: Svelte for Beginners"),
    );
    properties2.insert(
        "https://atomicdata.dev/properties/description".to_string(),
        json!("Getting started with Svelte, the reactive UI framework."),
    );
    properties2.insert(
        "https://atomicdata.dev/properties/parent".to_string(),
        json!(parent_subject),
    );

    store
        .create_with_commit(&article2_subject, properties2)
        .await
        .unwrap();

    // Give the server a moment to index the new resources
    tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;

    // 3. Instantiate the indexer
    let indexer = AtomicHaystackIndexer::default();

    // 4. Create a Haystack config
    let haystack = Haystack::new(
        config.server_url.clone(),
        terraphim_config::ServiceType::Atomic,
        true,
    )
    .with_atomic_secret(std::env::var("ATOMIC_SERVER_SECRET").ok());

    // Poll the server until the document is indexed or we time out
    let mut index = terraphim_types::Index::new();
    for _ in 0..10 {
        index = indexer.index("Rust", &haystack).await.unwrap();
        if !index.is_empty() {
            break;
        }
        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    }
    println!("Final search results: {:?}", index);

    assert_eq!(index.len(), 1);
    let doc = index.values().next().unwrap();
    assert_eq!(doc.title, "Test Article 1: The Magic of Rust");
    assert!(doc
        .description
        .as_ref()
        .unwrap()
        .contains("ownership model"));

    // Cleanup
    store.delete_with_commit(&article1_subject).await.unwrap();
    store.delete_with_commit(&article2_subject).await.unwrap();
    store.delete_with_commit(&parent_subject).await.unwrap();
}