use crate::error::{QdrantError, QdrantResult};
use crate::QdrantDriver;
use std::sync::Arc;
use tokio::sync::Semaphore;
#[derive(Debug, Clone)]
pub struct PoolConfig {
pub max_connections: usize,
pub connect_timeout_secs: u64,
pub request_timeout_secs: u64,
}
impl Default for PoolConfig {
fn default() -> Self {
Self {
max_connections: 10,
connect_timeout_secs: 5,
request_timeout_secs: 30,
}
}
}
pub struct QdrantPool {
driver: Arc<QdrantDriver>,
semaphore: Arc<Semaphore>,
#[allow(dead_code)]
config: PoolConfig,
}
impl QdrantPool {
pub async fn connect(host: &str, port: u16, config: PoolConfig) -> QdrantResult<Self> {
let driver = QdrantDriver::connect(host, port).await?;
Ok(Self {
driver: Arc::new(driver),
semaphore: Arc::new(Semaphore::new(config.max_connections)),
config,
})
}
pub async fn connect_addr(addr: &str, config: PoolConfig) -> QdrantResult<Self> {
let parts: Vec<&str> = addr.split(':').collect();
let host = parts.first().unwrap_or(&"localhost");
let port: u16 = parts.get(1).and_then(|p| p.parse().ok()).unwrap_or(6333);
Self::connect(host, port, config).await
}
pub async fn get(&self) -> QdrantResult<PooledConnection<'_>> {
let permit = self.semaphore
.clone()
.acquire_owned()
.await
.map_err(|e| QdrantError::Connection(e.to_string()))?;
Ok(PooledConnection {
driver: &self.driver,
_permit: permit,
})
}
pub fn driver(&self) -> &QdrantDriver {
&self.driver
}
pub fn available(&self) -> usize {
self.semaphore.available_permits()
}
}
pub struct PooledConnection<'a> {
driver: &'a QdrantDriver,
_permit: tokio::sync::OwnedSemaphorePermit,
}
impl<'a> std::ops::Deref for PooledConnection<'a> {
type Target = QdrantDriver;
fn deref(&self) -> &Self::Target {
self.driver
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pool_config_default() {
let config = PoolConfig::default();
assert_eq!(config.max_connections, 10);
assert_eq!(config.connect_timeout_secs, 5);
assert_eq!(config.request_timeout_secs, 30);
}
}