更新爆改前的备份

This commit is contained in:
zhanggangyong
2026-02-09 06:40:04 +00:00
parent a498072888
commit 368198f53c
9 changed files with 189 additions and 42 deletions
+16 -6
View File
@@ -7,7 +7,7 @@ metadata:
labels:
app: data-ingestion
spec:
replicas: 2
replicas: 1
selector:
matchLabels:
app: data-ingestion
@@ -24,6 +24,9 @@ spec:
- containerPort: 8000
name: http
env:
# 环境标识
- name: ENVIRONMENT
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
@@ -85,15 +88,22 @@ spec:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 5
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 15
periodSeconds: 5
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
failureThreshold: 5
# ACR 镜像拉取凭据
imagePullSecrets:
- name: acr-secret
---
apiVersion: v1
kind: Service
+2 -1
View File
@@ -22,8 +22,9 @@ stringData:
# ===========================================
# Redis配置 (Azure Cache for Redis with SSL)
# 端口 10000 使用 SSL 连接
# 注意:Redis 已迁移到 taiji2026 实例
# ===========================================
redis-url: "rediss://:nkJgt1ERFpdeYrEFNyFtsc5K4ycvx2jIeAzCaGGf1OQ%3D@taiji.southeastasia.redis.azure.net:10000/0?ssl_cert_reqs=none"
redis-url: "rediss://:PzmWkM6CwfRrJTB1d2xLRxE9pzT7JKgvVAzCaEehmFE=@taiji2026.southeastasia.redis.azure.net:10000/0?ssl_cert_reqs=none"
# ===========================================
# JWT配置
+13
View File
@@ -33,6 +33,7 @@ def register_lifecycle_events(app: FastAPI) -> None:
state = get_state()
settings = state.settings
# Redis 连接(允许失败,服务继续运行)
try:
state.redis_client = redis.from_url(
settings.redis_url,
@@ -42,11 +43,23 @@ def register_lifecycle_events(app: FastAPI) -> None:
await state.redis_client.ping()
redis_connections.set(1)
logger.info("Redis连接成功")
except Exception as redis_exc:
logger.warning("Redis连接失败,服务将继续运行(无缓存功能)", error=str(redis_exc))
state.redis_client = None
redis_connections.set(0)
# NATS 连接(允许失败)
try:
state.nats_client = await nats.connect(settings.nats_url)
nats_connections.set(1)
logger.info("NATS连接成功")
except Exception as nats_exc:
logger.warning("NATS连接失败,消息功能不可用", error=str(nats_exc))
state.nats_client = None
nats_connections.set(0)
# 初始化其他组件
try:
state.rapidapi_client = RapidAPIClient(
api_key=settings.rapidapi_key,
host=settings.rapidapi_host,
@@ -1495,6 +1495,22 @@ class AgentManagerClient:
data = await self._request("POST", "/external-tools/agents/create-with-tools", json=payload)
# 检查业务逻辑是否成功(agent-manager 可能返回 HTTP 200 但 success=false)
if isinstance(data, dict) and data.get("success") is False:
error_code = data.get("error", "unknown_error")
error_message = data.get("message", "创建 Agent 失败")
logger.error(
"create_agent_with_tools_failed",
name=name,
error_code=error_code,
error_message=error_message
)
raise AgentManagerError(
message=error_message,
status_code=400,
detail={"error": error_code, "message": error_message}
)
return AgentCreateResult(
name=data["name"],
namespace=data["namespace"],
+62 -32
View File
@@ -2238,6 +2238,21 @@ async def get_available_platform_agents(
template_configs_result = await db.execute(select(PlatformAgentTemplateConfig))
template_configs = {config.template_name: config for config in template_configs_result.scalars().all()}
# 查询实际运行的agent数量(基于计费记录)
running_count_result = await db.execute(
select(
AgentBillingRecord.agent_type,
func.count().label("count")
).where(
and_(
AgentBillingRecord.user_id == user_id,
AgentBillingRecord.is_platform_agent == True,
AgentBillingRecord.end_time.is_(None) # 正在运行
)
).group_by(AgentBillingRecord.agent_type)
)
running_counts = {row.agent_type: row.count for row in running_count_result.all()}
agents = []
for quota in quotas:
# 从模板配置中获取管理员设置的CPU和内存限制
@@ -2245,20 +2260,35 @@ async def get_available_platform_agents(
cpu_limit = template_config.cpu_limit if template_config and template_config.cpu_limit else "100m"
memory_limit = template_config.memory_limit if template_config and template_config.memory_limit else "256Mi"
# 使用实际运行的agent数量,而不是数据库中的pod_used
actual_used = running_counts.get(quota.template_name, 0)
# 如果数据库中的pod_used与实际不符,同步更新
if quota.pod_used != actual_used:
quota.pod_used = actual_used
logger.warning(
f"同步配额使用数: {quota.template_name} {quota.pod_used} -> {actual_used}",
user_id=user_id,
template=quota.template_name
)
agents.append({
"id": str(quota.id),
"templateName": quota.template_name,
"displayName": quota.template_name.replace("-", " ").replace("_", " ").title(),
"description": f"Platform Agent: {quota.template_name}",
"podQuota": quota.pod_quota,
"podUsed": quota.pod_used,
"podRemaining": quota.pod_quota - quota.pod_used,
"podUsed": actual_used, # 使用实际运行数量
"podRemaining": quota.pod_quota - actual_used,
"cpuLimit": cpu_limit,
"memoryLimit": memory_limit,
"category": "platform",
"allocatedAt": quota.allocated_at.isoformat() if quota.allocated_at else None,
})
# 提交配额同步更新
await db.commit()
return SuccessResponse(data={"agents": agents})
@@ -3169,44 +3199,44 @@ async def create_custom_agent(
client = get_agent_manager_client()
# ========== 自定义 Agent:使用外部数据工具创建 ==========
# 工具已在 Agent Manager 生成(有 tool_ref_id),直接使用 tool_refs 创建 Agent
# 工具已在 Agent Manager 生成(有 tool_ref_id),直接使用 tool_refs 创建 Agent
# =======================================================
if not external_tool_refs:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="没有可用的外部数据工具(需要 tool_ref_id)"
)
logger.info(
if not external_tool_refs:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="没有可用的外部数据工具(需要 tool_ref_id)"
)
logger.info(
f"创建自定义 Agent: name={req.name}, tool_refs={external_tool_refs}"
)
# 创建 Agent 配置
agent_config = AgentConfig(
user_id=str(user_id),
cpu_request=req.cpuRequest,
)
# 创建 Agent 配置
agent_config = AgentConfig(
user_id=str(user_id),
cpu_request=req.cpuRequest,
cpu_limit=req.cpuRequest, # limit 默认和 request 一致
memory_request=req.memoryRequest,
memory_request=req.memoryRequest,
memory_limit=req.memoryRequest, # limit 默认和 request 一致
replicas=1,
)
# 调用 create_agent_with_tools(使用 /external-tools/agents/create-with-tools 接口)
replicas=1,
)
# 调用 create_agent_with_tools(使用 /external-tools/agents/create-with-tools 接口)
# template 默认和 name 一致
template_name = req.name
result = await client.create_agent_with_tools(
name=req.name,
result = await client.create_agent_with_tools(
name=req.name,
template=template_name,
tool_refs=external_tool_refs,
config=agent_config,
env=env_vars
)
logger.info(
tool_refs=external_tool_refs,
config=agent_config,
env=env_vars
)
logger.info(
f"自定义 Agent 创建成功: name={req.name}, "
f"status={result.status}, tool_count={len(external_tool_refs)}"
)
f"status={result.status}, tool_count={len(external_tool_refs)}"
)
try:
# 更新配额使用量
+2 -1
View File
@@ -34,7 +34,8 @@ class Settings(BaseSettings):
)
# Redis设置(Azure Cache for Redis)
redis_url: str = "rediss://:nkJgt1ERFpdeYrEFNyFtsc5K4ycvx2jIeAzCaGGf1OQ%3D@taiji.southeastasia.redis.azure.net:10000/0?ssl_cert_reqs=none"
# 注意:Redis 已迁移到 taiji2026 实例
redis_url: str = "rediss://:PzmWkM6CwfRrJTB1d2xLRxE9pzT7JKgvVAzCaEehmFE=@taiji2026.southeastasia.redis.azure.net:10000/0?ssl_cert_reqs=none"
redis_max_connections: int = 20
redis_retry_on_timeout: bool = True
+2 -2
View File
@@ -11,8 +11,8 @@ stringData:
# 数据库连接字符串 - 使用 taiji 数据库
database-url: "postgresql+asyncpg://taiji:PASSWORD@taijipda.postgres.database.azure.com:5432/taiji?sslmode=require"
# Redis连接字符串
redis-url: "rediss://:REDIS_PASSWORD@taiji.southeastasia.redis.azure.net:10000/0?ssl_cert_reqs=none"
# Redis连接字符串(Redis 已迁移到 taiji2026 实例)
redis-url: "rediss://:PzmWkM6CwfRrJTB1d2xLRxE9pzT7JKgvVAzCaEehmFE=@taiji2026.southeastasia.redis.azure.net:10000/0?ssl_cert_reqs=none"
# JWT密钥
jwt-secret: "CHANGE_THIS_SECRET_KEY_IN_PRODUCTION"
@@ -0,0 +1,6 @@
-- 018: 修复 agent_billing_records 表 agent_type 字段长度
-- 问题: microsoft_learn_agent (22字符) 超出 VARCHAR(20) 限制
-- 解决: 将 agent_type 字段从 VARCHAR(20) 扩展到 VARCHAR(100)
ALTER TABLE agent_billing_records ALTER COLUMN agent_type TYPE VARCHAR(100);
@@ -0,0 +1,70 @@
#!/usr/bin/env python3
"""
运行 018 迁移:修复 agent_billing_records 表 agent_type 字段长度
问题: microsoft_learn_agent (22字符) 超出 VARCHAR(20) 限制
"""
import asyncio
import os
import sys
from pathlib import Path
# 添加项目根目录到 Python 路径
sys.path.insert(0, str(Path(__file__).parent.parent))
import asyncpg
async def run_migration():
"""执行迁移"""
# 获取数据库连接信息
database_url = os.getenv(
"DATABASE_URL",
"postgresql://postgres:postgres@localhost:5432/mcp_server"
)
# 解析连接字符串
if database_url.startswith("postgresql://"):
# 转换为 asyncpg 格式
database_url = database_url.replace("postgresql://", "postgres://")
print(f"连接数据库: {database_url.split('@')[1] if '@' in database_url else database_url}")
try:
conn = await asyncpg.connect(database_url)
print("数据库连接成功")
# 读取 SQL 文件
sql_file = Path(__file__).parent / "018_fix_agent_type_length.sql"
with open(sql_file, "r", encoding="utf-8") as f:
sql = f.read()
print("执行迁移 SQL...")
print(f"SQL: {sql}")
await conn.execute(sql)
print("迁移执行成功!")
# 验证字段类型
result = await conn.fetchrow(
"""
SELECT character_maximum_length
FROM information_schema.columns
WHERE table_name = 'agent_billing_records'
AND column_name = 'agent_type'
"""
)
if result and result['character_maximum_length'] == 100:
print("✅ agent_type 字段已扩展到 VARCHAR(100)")
else:
print(f"❌ 字段验证失败: {result}")
await conn.close()
except Exception as e:
print(f"迁移失败: {e}")
raise
if __name__ == "__main__":
asyncio.run(run_migration())