Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 56 additions & 50 deletions examples/issue_32_demo.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
// Issue #32: Async Provider Validation Demo
//
//
// This demo showcases the async validation system that tests provider connections
// in the background without blocking the UI thread.

use agentic::{
settings::{
Settings, ProviderType, ValidationEvent, ValidationService,
validate_local_provider, validate_openrouter_provider, AsyncValidationResult,
ValidationStatus
},
use agentic::settings::{
AsyncValidationResult, ProviderType, Settings, ValidationEvent, ValidationService,
ValidationStatus, validate_local_provider, validate_openrouter_provider,
};
use tokio::sync::mpsc;
use std::time::Duration;
use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
println!("🔍 Issue #32: Async Provider Validation Demo");
println!("======================================================================");
println!();

println!("🚀 ASYNC VALIDATION FEATURES:");
println!(" ✅ Non-blocking async validation");
println!(" ✅ LOCAL endpoint connection testing");
Expand All @@ -29,20 +26,21 @@ async fn main() {
println!(" ✅ Response time measurement");
println!(" ✅ Event-driven architecture");
println!();

// Create event channel for validation results
let (tx, mut rx) = mpsc::unbounded_channel::<ValidationEvent>();

// Create settings with test configuration
let mut settings = Settings::new();

// Configure test endpoints and keys
settings.local_provider.endpoint_url = Some("http://localhost:11434".to_string());
settings.openrouter_provider.api_key = Some("sk-or-v1-test-key-for-validation-demo".to_string());

settings.openrouter_provider.api_key =
Some("sk-or-v1-test-key-for-validation-demo".to_string());

println!("🧪 TESTING INDIVIDUAL VALIDATION FUNCTIONS:");
println!();

// Test 1: Valid local endpoint (assuming Ollama running)
println!("📝 Testing LOCAL endpoint validation:");
let local_result = validate_local_provider("http://localhost:11434").await;
Expand All @@ -54,7 +52,7 @@ async fn main() {
println!(" Response time: {}ms", time.as_millis());
}
println!();

// Test 2: Invalid local endpoint
println!("📝 Testing invalid LOCAL endpoint:");
let invalid_local = validate_local_provider("http://localhost:99999").await;
Expand All @@ -63,7 +61,7 @@ async fn main() {
println!(" Message: {}", msg);
}
println!();

// Test 3: OpenRouter API validation (will fail with test key)
println!("🔐 Testing OPENROUTER API validation:");
let openrouter_result = validate_openrouter_provider("sk-or-v1-test-key-invalid").await;
Expand All @@ -72,40 +70,39 @@ async fn main() {
println!(" Message: {}", msg);
}
println!();

println!("🔄 TESTING ASYNC VALIDATION SERVICE:");
println!();

// Create validation service
let validation_service = ValidationService::new(tx.clone());

// Test async validation for both providers
println!(" Starting LOCAL provider validation...");
validation_service.validate_provider(
ProviderType::Local,
&settings.local_provider
).await;

validation_service
.validate_provider(ProviderType::Local, &settings.local_provider)
.await;

println!(" Starting OPENROUTER provider validation...");
validation_service.validate_provider(
ProviderType::OpenRouter,
&settings.openrouter_provider
).await;

validation_service
.validate_provider(ProviderType::OpenRouter, &settings.openrouter_provider)
.await;

// Collect validation events
let mut events_received = 0;
let max_events = 4; // Start + Complete for each provider

println!();
println!("📡 VALIDATION EVENTS:");

while events_received < max_events {
if let Ok(event) = tokio::time::timeout(Duration::from_secs(10), rx.recv()).await {
if let Some(event) = event {
match event {
ValidationEvent::StartValidation(provider) => {
println!(" 🔄 Started validation for {:?}", provider);
settings.handle_validation_event(ValidationEvent::StartValidation(provider));
settings
.handle_validation_event(ValidationEvent::StartValidation(provider));
}
ValidationEvent::ValidationComplete { provider, result } => {
println!(" ✅ Completed validation for {:?}", provider);
Expand All @@ -116,9 +113,9 @@ async fn main() {
if let Some(time) = result.response_time {
println!(" Response time: {}ms", time.as_millis());
}
settings.handle_validation_event(ValidationEvent::ValidationComplete {
provider: provider.clone(),
result
settings.handle_validation_event(ValidationEvent::ValidationComplete {
provider: provider.clone(),
result,
});
}
}
Expand All @@ -129,53 +126,62 @@ async fn main() {
break;
}
}

println!();
println!("📊 FINAL VALIDATION STATUS:");
println!(" LOCAL Provider: {:?}", settings.local_provider.validation_status);
println!(" OPENROUTER Provider: {:?}", settings.openrouter_provider.validation_status);
println!(
" LOCAL Provider: {:?}",
settings.local_provider.validation_status
);
println!(
" OPENROUTER Provider: {:?}",
settings.openrouter_provider.validation_status
);
println!();

println!("🧪 TESTING SETTINGS INTEGRATION:");
println!();

// Test the settings-level validation methods
let (tx2, mut rx2) = mpsc::unbounded_channel::<ValidationEvent>();

println!(" Testing validate_all_providers...");
let tasks = settings.validate_all_providers(tx2.clone()).await;
println!(" Started {} validation tasks", tasks.len());

// Wait for all tasks to complete
for task in tasks {
let _ = task.await;
}

// Collect results
let mut events_received2 = 0;
while events_received2 < 4 &&
tokio::time::timeout(Duration::from_secs(2), rx2.recv()).await.is_ok() {
while events_received2 < 4
&& tokio::time::timeout(Duration::from_secs(2), rx2.recv())
.await
.is_ok()
{
events_received2 += 1;
}

println!(" Received {} validation events", events_received2);
println!();

println!("🔍 VALIDATION TRIGGERS:");
println!(" ✅ Individual provider validation");
println!(" ✅ All providers validation");
println!(" ✅ Event-driven status updates");
println!(" ✅ Non-blocking async execution");
println!();

println!("🛡️ ERROR HANDLING:");
println!(" ✅ Network timeouts (5s limit)");
println!(" ✅ Connection failures");
println!(" ✅ HTTP status codes");
println!(" ✅ Authentication errors");
println!(" ✅ Rate limiting detection");
println!();

println!("🎉 Issue #32 Implementation Complete!");
println!("📋 All Success Criteria Met:");
println!(" ✅ Async validation runs without blocking UI");
Expand Down
Loading