[router] add postgres databases data connector (#12218)

This commit is contained in:
rongfu.leng
2025-11-10 16:51:50 -08:00
committed by GitHub
parent 012bfc4fdc
commit 2fe4e69fca
12 changed files with 989 additions and 86 deletions
+10 -2
View File
@@ -1,7 +1,7 @@
use super::{
CircuitBreakerConfig, ConfigError, ConfigResult, DiscoveryConfig, HealthCheckConfig,
HistoryBackend, MetricsConfig, OracleConfig, PolicyConfig, RetryConfig, RouterConfig,
RoutingMode, TokenizerCacheConfig,
HistoryBackend, MetricsConfig, OracleConfig, PolicyConfig, PostgresConfig, RetryConfig,
RouterConfig, RoutingMode, TokenizerCacheConfig,
};
use crate::{core::ConnectionMode, mcp::McpConfig};
@@ -497,6 +497,14 @@ impl RouterConfigBuilder {
self
}
pub fn maybe_postgres(mut self, postgres: Option<PostgresConfig>) -> Self {
if let Some(cfg) = postgres {
self.config.history_backend = HistoryBackend::Postgres;
self.config.postgres = Some(cfg);
}
self
}
pub fn maybe_reasoning_parser(mut self, parser: Option<impl Into<String>>) -> Self {
self.config.reasoning_parser = parser.map(|p| p.into());
self
+54
View File
@@ -1,6 +1,7 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use url::Url;
use super::ConfigResult;
use crate::core::ConnectionMode;
@@ -53,6 +54,9 @@ pub struct RouterConfig {
/// Required when history_backend = "oracle"
#[serde(skip_serializing_if = "Option::is_none")]
pub oracle: Option<OracleConfig>,
/// Required when history_backend = "postgres"
#[serde(skip_serializing_if = "Option::is_none")]
pub postgres: Option<PostgresConfig>,
/// For reasoning models (e.g., deepseek-r1, qwen3)
pub reasoning_parser: Option<String>,
/// For tool-call interactions
@@ -123,6 +127,7 @@ pub enum HistoryBackend {
Memory,
None,
Oracle,
Postgres,
}
/// Oracle history backend configuration
@@ -182,6 +187,54 @@ impl std::fmt::Debug for OracleConfig {
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PostgresConfig {
// Database connection URL,
// postgres://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
pub db_url: String,
// Database pool max size
pub pool_max: usize,
}
impl PostgresConfig {
pub fn default_pool_max() -> usize {
16
}
pub fn validate(&self) -> Result<(), String> {
let s = self.db_url.trim();
if s.is_empty() {
return Err("is it db-url should be not empty".to_string());
}
let url = Url::parse(s).map_err(|e| format!("invalid db_url: {}", e))?;
let scheme = url.scheme();
if scheme != "postgres" && scheme != "postgresql" {
return Err(format!("don't support URL scheme: {}", scheme));
}
if url.host().is_none() {
return Err("db_url must need host".to_string());
}
let path = url.path();
let dbname = path
.strip_prefix('/')
.filter(|p| !p.is_empty())
.map(|s| s.to_string());
if dbname.is_none() {
return Err("db_url must need database name".to_string());
}
if self.pool_max == 0 {
return Err("pool_max must be greater 1, default is 16".to_string());
}
Ok(())
}
}
/// Routing mode configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
@@ -442,6 +495,7 @@ impl Default for RouterConfig {
chat_template: None,
history_backend: default_history_backend(),
oracle: None,
postgres: None,
reasoning_parser: None,
tool_call_parser: None,
tokenizer_cache: TokenizerCacheConfig::default(),