[router] add postgres databases data connector (#12218)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user