athena_rs 1.1.0

Database gateway API
Documentation
# Supabase SDK Integration with Health Tracking


This module provides a health-aware wrapper around the `supabase_rs` SDK, adding circuit breaker patterns, automatic failure tracking, and retry logic.

## Features


- **Health Tracking**: Monitors connection health and automatically circuits break on repeated failures
-**Circuit Breaker**: Temporarily blocks requests to failing hosts to prevent cascade failures
-**Automatic Recovery**: Hosts automatically recover after the offline period expires
-**Detailed Logging**: Structured logging with `tracing` for all operations
-**Drop-in Replacement**: Compatible API with the underlying `supabase_rs` SDK
-**Shared State**: Uses the same global health tracker as Scylla driver for unified monitoring

## Architecture


```
┌─────────────────────────────────────────┐
│   HealthAwareSupabaseClient             │
│  ┌───────────────────────────────────┐  │
│  │  SupabaseClient (supabase_rs)     │  │
│  └───────────────────────────────────┘  │
│              ▲                           │
│              │ wraps                     │
│  ┌───────────┴───────────────────────┐  │
│  │  HostHealthTracker (global)       │  │
│  │  - Failure counting               │  │
│  │  - Offline window management      │  │
│  │  - Circuit breaker logic          │  │
│  └───────────────────────────────────┘  │
└─────────────────────────────────────────┘
```

## Usage


### Basic Example


```rust
use athena_rs::drivers::supabase::client::{
    HealthAwareSupabaseClient,
    SupabaseConnectionInfo
};

#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create connection info
    let info = SupabaseConnectionInfo::new(
        "https://xxx.supabase.co".to_string(),
        "your-anon-key".to_string(),
    );
    
    // Create health-aware client
    let client = HealthAwareSupabaseClient::new(info)?;
    
    // Execute queries with automatic health tracking
    let users = client
        .select("users")
        .columns(vec!["id", "email"])
        .limit(10)
        .execute()
        .await?;
    
    println!("Got {} users", users.len());
    Ok(())
}
```

### From Environment Variables


```rust
use athena_rs::drivers::supabase::client::HealthAwareSupabaseClient;

// Load from SUPABASE_URL and SUPABASE_KEY env vars
let athena = HealthAwareSupabaseClient::from_env(
    "SUPABASE_URL",
    "SUPABASE_KEY"
)?;

let results = athena
    .select("products")
    .eq("status", "active")
    .order("created_at", false)
    .execute()
    .await?;
```

### Query Building


The client supports the full query builder API:

```rust
let results = client
    .select("orders")
    .columns(vec!["id", "user_id", "total", "status"])
    .eq("status", "completed")           // Equality filter
    .gt("total", "100")                  // Greater than
    .lt("created_at", "2024-01-01")     // Less than
    .order("created_at", false)          // Order descending
    .limit(50)                           // Limit results
    .offset(100)                         // Pagination
    .execute()
    .await?;
```

### Insert, Update, Delete


```rust
use serde_json::json;

// Insert
let new_user = json!({
    "email": "user@example.com",
    "name": "John Doe"
});
let user_id = client.insert("users", new_user).await?;

// Update
let updates = json!({
    "name": "Jane Doe",
    "updated_at": "2024-02-08T12:00:00Z"
});
client.update("users", &user_id, updates).await?;

// Delete
client.delete("users", &user_id).await?;
```

### Health Monitoring


```rust
// Check if host is currently offline
if let Some(offline_until) = client.is_offline() {
    println!("Host is offline until {:?}", offline_until);
} else {
    println!("Host is healthy");
}

// Force offline for testing (e.g., maintenance window)
use std::time::Duration;
client.force_offline(Duration::from_secs(300)); // 5 minutes

// Reset health tracking (clear all failures)
client.reset_health();
```

## Configuration


### Health Tracking Defaults


The global health tracker uses these defaults (shared with Scylla driver):

```rust
const FAILURE_THRESHOLD: usize = 5;      // Failures before circuit break
const FAILURE_WINDOW: Duration = 60s;    // Window to count failures
const OFFLINE_DURATION: Duration = 300s; // How long to stay offline
```

These can be customized by creating your own `HostHealthTracker` instance.

### Environment Variables


```bash
# Standard Supabase connection

export SUPABASE_URL="https://xxx.supabase.co"
export SUPABASE_KEY="your-anon-or-service-role-key"

# Multiple projects

export SUPABASE_XBP_URL="https://yyy.supabase.co"
export SUPABASE_XBP_KEY="another-key"

# Logging level

export RUST_LOG="info,athena_rs::drivers::supabase=debug"
```

## Error Handling


The client can return two main error types:

### 1. HostOffline Error


When the circuit breaker trips:

```rust
match client.select("users").execute().await {
    Err(e) if e.is::<HostOffline>() => {
        let offline = e.downcast::<HostOffline>()?;
        println!("Host {} is offline until {:?}", 
            offline.host(), offline.until());
    }
    Err(e) => println!("Other error: {}", e),
    Ok(data) => println!("Success!"),
}
```

### 2. Query/Connection Errors


Standard errors from the underlying SDK:

```rust
match client.select("users").execute().await {
    Ok(data) => process_data(data),
    Err(e) => {
        // Could be network error, auth error, query syntax, etc.
        log::error!("Query failed: {}", e);
    }
}
```

## Integration with Existing Code


### Migrating from Direct `supabase_rs` Usage


**Before:**

```rust
use supabase_rs::SupabaseClient;

let client = SupabaseClient::new(url, key)?;
let data = client.select("users")
    .columns(vec!["id", "email"])
    .execute()
    .await?;
```

**After:**

```rust
use athena_rs::drivers::supabase::client::{
    HealthAwareSupabaseClient,
    SupabaseConnectionInfo
};

let info = SupabaseConnectionInfo::new(url, key);
let client = HealthAwareSupabaseClient::new(info)?;
let data = client.select("users")
    .columns(vec!["id", "email"])
    .execute()
    .await?;
```

The API is nearly identical, with added health tracking benefits!

## Testing


Run the example:

```bash
cargo run --example supabase_health_tracking
```

Run tests:

```bash
cargo test --package athena_rs --lib drivers::supabase::client
```

## Advanced: Custom Health Tracker


If you need different health tracking parameters:

```rust
use athena_rs::drivers::scylla::health::{HostHealthTracker, SystemClock};
use std::time::Duration;

// Create custom tracker with stricter thresholds
let tracker = HostHealthTracker::new(
    SystemClock::default(),
    3,                              // Fail after 3 errors
    Duration::from_secs(30),        // 30 second window
    Duration::from_secs(60),        // 1 minute offline
);

// Note: You'd need to modify the client to accept a custom tracker
// or use it directly for manual health checks
```

## Logging


The module uses `tracing` for structured logging:

```rust
// Enable debug logging
std::env::set_var("RUST_LOG", "debug");
tracing_subscriber::fmt::init();

// Logs include:
// - host: The Supabase host being accessed
// - table: Table name for queries
// - rows: Result row counts
// - error: Error details on failures
```

Example log output:

```
INFO  athena_rs::drivers::supabase::client: Supabase query succeeded
    host: xxx.supabase.co
    table: users
    rows: 42

ERROR athena_rs::drivers::supabase::client: Supabase query failed
    host: xxx.supabase.co
    table: orders
    error: Connection timeout

WARN  athena_rs::drivers::supabase::client: Forcing Supabase host offline
    host: xxx.supabase.co
    duration_secs: 300
```

## Comparison with Legacy Functions


The module still exports legacy helper functions for backward compatibility:

```rust
// Legacy (still works)
use athena_rs::drivers::supabase::{supabase, supabase_xbp};
let client = supabase().await?;

// New (recommended)
use athena_rs::drivers::supabase::client::HealthAwareSupabaseClient;
let client = HealthAwareSupabaseClient::from_env("SUPABASE_URL", "SUPABASE_KEY")?;
```

The new client is recommended for all new code due to:
- Health tracking and circuit breaking
- Better error handling
- Detailed logging
- Consistent API with other drivers

## See Also


- [Supabase RS SDK Documentation]https://docs.rs/supabase_rs
- [Scylla Health Tracking]../scylla/health.rs
- [Circuit Breaker Pattern]https://martinfowler.com/bliki/CircuitBreaker.html