- strawberry-graphql[asgi] dependency added - 13 Federation 2 types: ClassPerformance/StudentWeakness/Dashboards/Mastery/ErrorBook - 11 Query resolvers delegate to existing analytics/mastery services - RouterAuthMiddleware validates Router-Authorization header on /graphql - GraphQL endpoint mounted at /graphql alongside existing REST endpoints
110 lines
3.7 KiB
Python
110 lines
3.7 KiB
Python
"""配置管理(pydantic-settings 完整配置项).
|
||
|
||
对齐 02-architecture-design.md §15 配置清单.
|
||
环境变量前缀 DATA_ANA_(如 DATA_ANA_HTTP_PORT=3006).
|
||
"""
|
||
|
||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||
|
||
|
||
class Settings(BaseSettings):
|
||
"""应用配置.
|
||
|
||
所有外部依赖(ClickHouse / Kafka / Redis / iam gRPC)均为可选:
|
||
未配置或不可达时服务进入降级模式,返回骨架数据 + details.degraded: true.
|
||
"""
|
||
|
||
# 服务
|
||
service_name: str = "data-ana"
|
||
http_port: int = 3006
|
||
grpc_port: int = 50055
|
||
log_level: str = "INFO"
|
||
dev_mode: bool = False
|
||
|
||
# ClickHouse(可选:留空则降级模式)
|
||
clickhouse_host: str = ""
|
||
clickhouse_port: int = 8123
|
||
clickhouse_database: str = "edu_analytics"
|
||
clickhouse_user: str = ""
|
||
clickhouse_password: str = ""
|
||
clickhouse_connect_timeout_ms: int = 3000
|
||
clickhouse_query_timeout_s: int = 3 # P4 退出标准 5s,查询 3s 超时降级
|
||
|
||
# Kafka
|
||
kafka_brokers: str = "" # 留空则不启动 CDC 消费者
|
||
kafka_consumer_group: str = "data-ana-cdc"
|
||
kafka_cdc_topics: str = (
|
||
"edu-cdc.next_edu_cloud.core_edu_grades,"
|
||
"edu-cdc.next_edu_cloud.core_edu_exams,"
|
||
"edu-cdc.next_edu_cloud.core_edu_homework_submissions,"
|
||
"edu-cdc.next_edu_cloud.core_edu_attendance,"
|
||
"edu-cdc.next_edu_cloud.classes,"
|
||
"edu-cdc.next_edu_cloud.iam_users,"
|
||
"edu-cdc.next_edu_cloud.content_knowledge_points"
|
||
)
|
||
kafka_mastery_topic: str = "edu.insight.mastery.updated"
|
||
kafka_warning_topic: str = "edu.insight.mastery.updated" # 复用 mastery topic(总裁裁决 §2.11)
|
||
kafka_ai_usage_topic: str = "edu.insight.ai.usage"
|
||
kafka_enable_auto_commit: bool = False # v2: 手动 commit(at-least-once)
|
||
kafka_auto_offset_reset: str = "latest"
|
||
kafka_producer_transactional_id: str = "data-ana-producer"
|
||
|
||
# iam gRPC
|
||
iam_grpc_endpoint: str = "" # 留空则使用降级兜底(按 role 映射 DataScope)
|
||
iam_grpc_timeout_s: int = 2
|
||
datascope_cache_ttl_s: int = 300 # 5min
|
||
|
||
# Redis
|
||
redis_url: str = "" # 留空则跳过缓存
|
||
redis_pool_size: int = 10
|
||
redis_socket_timeout_ms: int = 200
|
||
|
||
# OTel
|
||
otel_endpoint: str = "http://localhost:4318"
|
||
otel_service_name: str = "data-ana"
|
||
|
||
# 掌握度算法
|
||
mastery_window_size: int = 5
|
||
mastery_decay_base: float = 0.6
|
||
mastery_forgetting_half_life_days: int = 30
|
||
mastery_min_samples: int = 3
|
||
|
||
# 预警阈值
|
||
warning_low_mastery_threshold: float = 0.4
|
||
warning_critical_mastery_threshold: float = 0.2
|
||
warning_score_drop_percent: float = 0.2
|
||
warning_absent_per_week: int = 3
|
||
|
||
# 降级
|
||
degraded_mode_enabled: bool = True
|
||
|
||
# P6 readyz 深度硬化
|
||
readyz_clickhouse_timeout_s: float = 1.0
|
||
readyz_redis_timeout_s: float = 0.2
|
||
readyz_iam_grpc_timeout_s: float = 2.0
|
||
readyz_cdc_lag_threshold: int = 1000 # lag 超过此值判定 not_ready
|
||
|
||
# GraphQL Federation 2 子图(v2.1 M1,ADR-036)
|
||
# Apollo Router 请求子图时必须携带 Router-Authorization Header(共享密钥)
|
||
# 与 TS 服务使用相同的 secret(由 Secret 注入)
|
||
router_auth_secret: str = "" # 留空则 /graphql 返回 403(除非 dev_mode=True)
|
||
graphql_path: str = "/graphql" # GraphQL 端点路径
|
||
|
||
# 向后兼容:旧代码引用 settings.port / settings.kafka_group_id
|
||
@property
|
||
def port(self) -> int:
|
||
return self.http_port
|
||
|
||
@property
|
||
def kafka_group_id(self) -> str:
|
||
return self.kafka_consumer_group
|
||
|
||
model_config = SettingsConfigDict(
|
||
env_file=".env",
|
||
env_prefix="DATA_ANA_",
|
||
extra="ignore",
|
||
)
|
||
|
||
|
||
settings = Settings()
|