do-memory-storage-turso 0.1.30

Turso/libSQL storage backend for the do-memory-core episodic learning system
Documentation
//! TursoStorage Adaptive Pool Constructor
//!
//! This module contains the adaptive pool constructor method for TursoStorage:
//! - new_with_adaptive_pool()

use do_memory_core::Result;
use libsql::Builder;
use std::sync::Arc;
use tracing::info;

use super::super::{
    AdaptiveConnectionPool, AdaptivePoolConfig, PreparedCacheConfig, PreparedStatementCache,
    TursoConfig,
};
use super::storage::TursoStorage;

impl TursoStorage {
    /// Create a new Turso storage instance with adaptive connection pool
    ///
    /// The adaptive pool automatically adjusts its size based on load:
    /// - Scales up when utilization exceeds threshold (default: 70%)
    /// - Scales down during low utilization (default: <30%)
    /// - Provides 20% better performance under variable load
    ///
    /// # Arguments
    ///
    /// * `url` - Database URL
    /// * `token` - Authentication token
    /// * `config` - Turso configuration
    /// * `adaptive_config` - Adaptive pool configuration
    ///
    /// # Example
    ///
    /// ```no_run
    /// use do_memory_storage_turso::{TursoStorage, TursoConfig, AdaptivePoolConfig};
    /// use std::time::Duration;
    ///
    /// # async fn example() -> anyhow::Result<()> {
    /// let config = TursoConfig::default();
    /// let adaptive_config = AdaptivePoolConfig {
    ///     min_connections: 5,
    ///     max_connections: 50,
    ///     scale_up_threshold: 0.7,
    ///     scale_down_threshold: 0.3,
    ///     scale_up_cooldown: Duration::from_secs(10),
    ///     scale_down_cooldown: Duration::from_secs(30),
    ///     scale_up_increment: 5,
    ///     scale_down_decrement: 5,
    ///     check_interval: Duration::from_secs(5),
    /// };
    ///
    /// let storage = TursoStorage::new_with_adaptive_pool(
    ///     "libsql://localhost:8080",
    ///     "token",
    ///     config,
    ///     adaptive_config
    /// ).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn new_with_adaptive_pool(
        url: &str,
        token: &str,
        config: TursoConfig,
        adaptive_config: AdaptivePoolConfig,
    ) -> Result<Self> {
        info!("Connecting to Turso database at {} with adaptive pool", url);

        // SECURITY: Enforce TLS for remote connections
        if !url.starts_with("libsql://")
            && !url.starts_with("file:")
            && !url.starts_with(":memory:")
        {
            return Err(do_memory_core::Error::Security(format!(
                "Insecure database URL: {}. Only libsql://, file:, or :memory: protocols are allowed",
                url
            )));
        }

        // SECURITY: Validate token is provided for remote connections
        if url.starts_with("libsql://") && token.trim().is_empty() {
            return Err(do_memory_core::Error::Security(
                "Authentication token required for remote Turso connections".to_string(),
            ));
        }

        let db = if url.starts_with("libsql://") {
            Builder::new_remote(url.to_string(), token.to_string())
                .build()
                .await
                .map_err(|e| {
                    do_memory_core::Error::Storage(format!("Failed to connect to Turso: {}", e))
                })?
        } else {
            let path = if let Some(stripped) = url.strip_prefix("file:") {
                stripped
            } else {
                url
            };
            Builder::new_local(path).build().await.map_err(|e| {
                do_memory_core::Error::Storage(format!("Failed to connect to Turso: {}", e))
            })?
        };

        let db = Arc::new(db);

        // Create adaptive connection pool
        let adaptive_pool =
            AdaptiveConnectionPool::new(Arc::clone(&db), adaptive_config.clone()).await?;
        info!(
            "Adaptive connection pool enabled (min={}, max={}, threshold={})",
            adaptive_config.min_connections,
            adaptive_config.max_connections,
            adaptive_config.scale_up_threshold
        );

        info!("Successfully connected to Turso database");

        Ok(Self {
            db,
            pool: None,
            #[cfg(feature = "keepalive-pool")]
            keepalive_pool: None,
            adaptive_pool: Some(Arc::new(adaptive_pool)),
            caching_pool: None,
            prepared_cache: Arc::new(PreparedStatementCache::with_config(
                PreparedCacheConfig::default(),
            )),
            config,
            #[cfg(feature = "compression")]
            compression_stats: Arc::new(std::sync::Mutex::new(
                super::super::CompressionStatistics::new(),
            )),
            #[cfg(feature = "adaptive-ttl")]
            episode_cache: None,
        })
    }
}