use fraiseql_wire::{connection::ConnectionConfig, FraiseClient};
use std::env;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_max_level(
env::var("RUST_LOG")
.ok()
.and_then(|l| l.parse().ok())
.unwrap_or(tracing::Level::INFO),
)
.init();
println!("╔════════════════════════════════════════════════════════════════╗");
println!("║ fraiseql-wire: Connection Configuration Example ║");
println!("║ ║");
println!("║ Demonstrates timeout, keepalive, and application name ║");
println!("║ configuration options for database connections ║");
println!("╚════════════════════════════════════════════════════════════════╝");
println!();
let host = env::var("POSTGRES_HOST").unwrap_or_else(|_| "localhost".to_string());
let port = env::var("POSTGRES_PORT").unwrap_or_else(|_| "5432".to_string());
let user = env::var("POSTGRES_USER").unwrap_or_else(|_| "postgres".to_string());
let password = env::var("POSTGRES_PASSWORD").unwrap_or_else(|_| "postgres".to_string());
let database = env::var("POSTGRES_DB").unwrap_or_else(|_| "postgres".to_string());
let connection_string = format!("postgres://{}:{}/{}", host, port, database);
println!("📊 Configuration Examples\n");
println!("Connection: {}@{}:{}/{}", user, host, port, database);
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("Example 1: Basic Connection (no special configuration)");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
println!("Code:");
println!(" let client = FraiseClient::connect(&connection_string).await?;");
println!();
match FraiseClient::connect(&connection_string).await {
Ok(_client) => println!("✓ Connected successfully with default configuration"),
Err(e) => println!("✗ Connection failed: {}", e),
}
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("Example 2: Configuration with Statement Timeout");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
println!("Code:");
println!(" let config = ConnectionConfig::builder(&database, &user)");
println!(" .password(&password)");
println!(" .statement_timeout(Duration::from_secs(30))");
println!(" .build();");
println!(" let client = FraiseClient::connect_with_config(&conn_string, config).await?;");
println!();
let config = ConnectionConfig::builder(&database, &user)
.password(&password)
.statement_timeout(Duration::from_secs(30))
.build();
println!("Configuration details:");
println!(" - statement_timeout: 30 seconds");
println!(" (Queries will be terminated if they exceed 30 seconds)");
println!();
match FraiseClient::connect_with_config(&connection_string, config).await {
Ok(_client) => {
println!("✓ Connected successfully with statement timeout configuration");
}
Err(e) => {
println!("✗ Connection failed: {}", e);
}
}
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("Example 3: Full Configuration (All Options)");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
println!("Code:");
println!(" let config = ConnectionConfig::builder(&database, &user)");
println!(" .password(&password)");
println!(" .statement_timeout(Duration::from_secs(60))");
println!(" .keepalive_idle(Duration::from_secs(300))");
println!(" .application_name(\"fraiseql_example\")");
println!(" .extra_float_digits(2)");
println!(" .build();");
println!();
let full_config = ConnectionConfig::builder(&database, &user)
.password(&password)
.statement_timeout(Duration::from_secs(60))
.keepalive_idle(Duration::from_secs(300))
.application_name("fraiseql_example")
.extra_float_digits(2)
.build();
println!("Configuration details:");
println!(" - statement_timeout: 60 seconds");
println!(" (Queries terminate after 60 seconds of execution)");
println!(" - keepalive_idle: 300 seconds (5 minutes)");
println!(" (TCP keepalive probes sent every 5 minutes during idle)");
println!(" - application_name: \"fraiseql_example\"");
println!(" (Visible in PostgreSQL logs and pg_stat_activity)");
println!(" - extra_float_digits: 2");
println!(" (Increased precision for floating point values)");
println!();
match FraiseClient::connect_with_config(&connection_string, full_config).await {
Ok(_client) => {
println!("✓ Connected successfully with full configuration");
}
Err(e) => {
println!("✗ Connection failed: {}", e);
}
}
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("Example 4: Builder Pattern (Fluent API)");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
println!("The ConnectionConfigBuilder uses a fluent API for easy chaining:");
println!();
let builder_config = ConnectionConfig::builder("mydb", "user")
.password("secret")
.statement_timeout(Duration::from_secs(45))
.keepalive_idle(Duration::from_secs(600))
.application_name("fluent_example")
.param("timezone", "UTC")
.build();
println!("Code:");
println!(" ConnectionConfig::builder(\"mydb\", \"user\")");
println!(" .password(\"secret\")");
println!(" .statement_timeout(Duration::from_secs(45))");
println!(" .keepalive_idle(Duration::from_secs(600))");
println!(" .application_name(\"fluent_example\")");
println!(" .param(\"timezone\", \"UTC\")");
println!(" .build()");
println!();
println!("Built configuration:");
println!(" - database: {}", builder_config.database);
println!(" - user: {}", builder_config.user);
println!(
" - statement_timeout: {:?}",
builder_config.statement_timeout
);
println!(" - keepalive_idle: {:?}", builder_config.keepalive_idle);
println!(
" - application_name: {:?}",
builder_config.application_name
);
println!(
" - custom param (timezone): {:?}",
builder_config.params.get("timezone")
);
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("Example 5: Timeout Value Conversions");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
println!("Timeouts are converted to milliseconds for PostgreSQL:");
println!();
let examples = vec![
(Duration::from_secs(1), "1 second"),
(Duration::from_millis(500), "500 milliseconds"),
(
Duration::from_secs(5) + Duration::from_millis(250),
"5.25 seconds",
),
(Duration::from_secs(30), "30 seconds"),
(Duration::from_secs(300), "5 minutes"),
];
for (duration, description) in examples {
println!(
" {} ({:?}) → {} ms",
description,
duration,
duration.as_millis()
);
}
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("Example 6: Using connect_with_config_and_tls");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
println!("You can also combine configuration with TLS encryption:");
println!();
println!("Code:");
println!(" let config = ConnectionConfig::builder(&database, &user)");
println!(" .password(&password)");
println!(" .statement_timeout(Duration::from_secs(30))");
println!(" .build();");
println!();
println!(" let tls = TlsConfig::builder()");
println!(" .verify_hostname(true)");
println!(" .build()?;");
println!();
println!(" let client = FraiseClient::connect_with_config_and_tls(");
println!(" connection_string,");
println!(" config,");
println!(" tls");
println!(" ).await?;");
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
println!("✨ Configuration examples complete!");
println!();
println!("Key takeaways:");
println!(" - Use ConnectionConfig::builder() for advanced options");
println!(" - statement_timeout: Limits query execution time");
println!(" - keepalive_idle: Prevents connection timeout on idle");
println!(" - application_name: Identifies your app in PostgreSQL logs");
println!(" - extra_float_digits: Controls floating point precision");
println!(" - All options are optional; defaults work for most cases");
println!();
Ok(())
}