feat: V1 - DAG编排/告警系统/Agent循环/知识库RAG/Webhook + 审核管理富上下文修复
This commit is contained in:
@@ -0,0 +1,101 @@
|
|||||||
|
"""Alert service: budget monitoring and system alerts."""
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from typing import List, Optional
|
||||||
|
from app.models.alert import Alert
|
||||||
|
from app.models.project import Project
|
||||||
|
from app.models.worker import AIWorker
|
||||||
|
from app.services.cost_service import CostService
|
||||||
|
|
||||||
|
|
||||||
|
class AlertService:
|
||||||
|
@staticmethod
|
||||||
|
def check_and_alert(db: Session, tenant_id: int, project_id: int) -> Optional[Alert]:
|
||||||
|
"""Check project budget and create alert if needed."""
|
||||||
|
project = db.query(Project).filter(
|
||||||
|
Project.id == project_id, Project.tenant_id == tenant_id
|
||||||
|
).first()
|
||||||
|
if not project or not project.budget_limit_cents:
|
||||||
|
return None
|
||||||
|
|
||||||
|
spent = CostService.get_project_cost(db, tenant_id, project_id)
|
||||||
|
limit = project.budget_limit_cents
|
||||||
|
pct = (spent / limit) if limit > 0 else 0
|
||||||
|
|
||||||
|
if pct >= 1.0:
|
||||||
|
# Pause project
|
||||||
|
project.status = "paused"
|
||||||
|
db.commit()
|
||||||
|
return AlertService._create(
|
||||||
|
db, tenant_id, "budget_exceeded", "critical",
|
||||||
|
f"项目「{project.name}」预算已超限!已花费 ¥{spent/100:.2f} / ¥{limit/100:.2f},项目已自动暂停。",
|
||||||
|
project_id=project_id,
|
||||||
|
)
|
||||||
|
elif pct >= 0.8:
|
||||||
|
return AlertService._create(
|
||||||
|
db, tenant_id, "budget_warning", "warning",
|
||||||
|
f"项目「{project.name}」预算使用达 {pct*100:.0f}%(¥{spent/100:.2f} / ¥{limit/100:.2f})",
|
||||||
|
project_id=project_id,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_worker_budget(db: Session, tenant_id: int, worker_id: int) -> Optional[Alert]:
|
||||||
|
worker = db.query(AIWorker).filter(
|
||||||
|
AIWorker.id == worker_id, AIWorker.tenant_id == tenant_id
|
||||||
|
).first()
|
||||||
|
if not worker or not worker.max_cost_per_month_cents:
|
||||||
|
return None
|
||||||
|
|
||||||
|
spent = CostService.get_worker_monthly_cost(db, tenant_id, worker_id)
|
||||||
|
limit = worker.max_cost_per_month_cents
|
||||||
|
pct = (spent / limit) if limit > 0 else 0
|
||||||
|
|
||||||
|
if pct >= 1.0:
|
||||||
|
worker.is_active = False
|
||||||
|
db.commit()
|
||||||
|
return AlertService._create(
|
||||||
|
db, tenant_id, "budget_exceeded", "critical",
|
||||||
|
f"Worker「{worker.name}」月度预算已超限!已花费 ¥{spent/100:.2f} / ¥{limit/100:.2f},Worker已停用。",
|
||||||
|
worker_id=worker_id,
|
||||||
|
)
|
||||||
|
elif pct >= 0.8:
|
||||||
|
return AlertService._create(
|
||||||
|
db, tenant_id, "budget_warning", "warning",
|
||||||
|
f"Worker「{worker.name}」月度预算使用达 {pct*100:.0f}%",
|
||||||
|
worker_id=worker_id,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _create(db, tenant_id, alert_type, severity, message, project_id=None, worker_id=None):
|
||||||
|
alert = Alert(
|
||||||
|
tenant_id=tenant_id, alert_type=alert_type, severity=severity,
|
||||||
|
message=message, project_id=project_id, worker_id=worker_id,
|
||||||
|
)
|
||||||
|
db.add(alert)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(alert)
|
||||||
|
return alert
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def list_alerts(db, tenant_id, is_read=None, skip=0, limit=50):
|
||||||
|
q = db.query(Alert).filter(Alert.tenant_id == tenant_id)
|
||||||
|
if is_read is not None:
|
||||||
|
q = q.filter(Alert.is_read == is_read)
|
||||||
|
return q.order_by(Alert.created_at.desc()).offset(skip).limit(limit).all()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def unread_count(db, tenant_id):
|
||||||
|
return db.query(Alert).filter(
|
||||||
|
Alert.tenant_id == tenant_id, Alert.is_read == False
|
||||||
|
).count()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mark_read(db, tenant_id, alert_id):
|
||||||
|
alert = db.query(Alert).filter(
|
||||||
|
Alert.id == alert_id, Alert.tenant_id == tenant_id
|
||||||
|
).first()
|
||||||
|
if alert:
|
||||||
|
alert.is_read = True
|
||||||
|
db.commit()
|
||||||
|
return alert
|
||||||
Reference in New Issue
Block a user