feat(data-ana): 完整实现 data-ana 数据分析服务

包含 CDC consumer、analytics/mastery/warning service、grpc server、repository、ClickHouse DDL 等
This commit is contained in:
SpecialX
2026-07-10 19:09:27 +08:00
parent 033057a302
commit ca3780aa24
29 changed files with 5401 additions and 383 deletions

View File

@@ -1,46 +1,97 @@
"""配置管理."""
"""配置管理pydantic-settings 完整配置项).
from pydantic_settings import BaseSettings
对齐 02-architecture-design.md §15 配置清单.
环境变量前缀 DATA_ANA_如 DATA_ANA_HTTP_PORT=3006.
"""
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""应用配置.
ClickHouse 连接参数为可选:当 clickhouse_host 为空字符串时,
服务进入降级模式(查询方法返回 None / 空数据),保证服务可启动。
Kafka 连接参数为可选:当 kafka_brokers 为空字符串时,
CDC 消费者不启动(降级模式),保证服务可启动。
所有外部依赖(ClickHouse / Kafka / Redis / iam gRPC均为可选
未配置或不可达时服务进入降级模式,返回骨架数据 + details.degraded: true.
"""
port: int = 3006
# ClickHouse 连接(可选:留空则降级模式)
# 服务
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 = ""
# 可观测性
otel_endpoint: str = "http://localhost:4318"
log_level: str = "info"
# 开发模式开关
dev_mode: bool = False
# Kafka brokersCDC 消费;留空则不启动消费者)
# 主机访问用 localhost:9092容器内访问用 kafka:29092
kafka_brokers: str = ""
# CDC 消费组 id
kafka_group_id: str = "data-ana-cdc-consumer"
# 要消费的 CDC topicDebezium 默认命名:<prefix>.<database>.<table>
# 用逗号分隔多个 topic
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.classes"
"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"
)
# 消费者自动偏移重置策略earliest / latest
kafka_auto_offset_reset: str = "earliest"
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: 手动 commitat-least-once
kafka_auto_offset_reset: str = "latest"
kafka_producer_transactional_id: str = "data-ana-producer"
model_config = {"env_file": ".env", "env_prefix": ""}
# 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
# 向后兼容:旧代码引用 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()