feat(ai): temporal worker for lesson plan workflow

- deploy temporal server (postgresql + auto-setup + ui) in docker-compose
- new temporal/ module: workflow + activities + worker manager
- convert lesson plan 4-step orchestration to temporal workflow
- activities wrap existing analyze/recommend/generate/prepare_review steps
- worker injects failover_chain/content_client/data_ana_client via module globals
- start() uses temporal client.start_workflow, falls back to asyncio in dev
- register temporal ports 7233/8085 in port-allocation

Implements M6.5 of v2.1 migration plan (ADR-030).
This commit is contained in:
SpecialX
2026-07-15 02:34:34 +08:00
parent ce5aeec955
commit 47e950c664
11 changed files with 701 additions and 40 deletions

View File

@@ -346,6 +346,63 @@ services:
interval: 15s
timeout: 5s
retries: 5
# ============================================================
# Temporal Server - AI 工作流引擎v2.1 §8.2 ADR-030
# 仅用于 AI 耗时工作流 + SagaCRUD 短事务禁止
# ============================================================
temporal-postgresql:
image: docker.m.daocloud.io/library/postgres:13
container_name: edu-temporal-postgres
profiles: ["p3", "p4", "p5", "p6"]
restart: unless-stopped
environment:
POSTGRES_USER: temporal
POSTGRES_PASSWORD: ${TEMPORAL_POSTGRES_PASSWORD:-temporal}
POSTGRES_DB: temporal
volumes:
- temporal_pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U temporal"]
interval: 10s
timeout: 5s
retries: 5
temporal:
image: temporalio/auto-setup:1.23
container_name: edu-temporal
profiles: ["p3", "p4", "p5", "p6"]
restart: unless-stopped
depends_on:
temporal-postgresql:
condition: service_healthy
environment:
DBHOST: temporal-postgresql
DBPORT: 5432
DBUSER: temporal
DBPASSWORD: ${TEMPORAL_POSTGRES_PASSWORD:-temporal}
DBNAME: temporal
DB_PLUGIN: postgres
# 暴露 frontend gRPC 端口 7233 供 Worker 连接
SERVICES: "frontend,history,matching,worker"
ports:
- "7233:7233"
healthcheck:
test: ["CMD", "tctl", "--address", "localhost:7233", "cluster", "health"]
interval: 15s
timeout: 5s
start_period: 30s
retries: 10
temporal-ui:
image: temporalio/ui:2.30.0
container_name: edu-temporal-ui
profiles: ["p3", "p4", "p5", "p6"]
restart: unless-stopped
depends_on:
- temporal
environment:
TEMPORAL_ADDRESS: temporal:7233
TEMPORAL_CORS_ORIGINS: "http://localhost:4000,http://localhost:4001,http://localhost:4002,http://localhost:4003"
ports:
- "8085:8080"
volumes:
mysql_data:
redis_data:
@@ -356,3 +413,4 @@ volumes:
prometheus_data:
alertmanager_data:
loki_data:
temporal_pg_data:

View File

@@ -93,24 +93,27 @@
## 6. 基础设施端口9080-9199
| 服务 | 端口 | 说明 |
| ---------------- | --------------------------------------------------------------------------- | ------------------------------------- |
| MySQL | 3306 | 业务数据库external |
| Redis | 6379 | 缓存 + 会话 + Pub/Sub |
| Kafka | 9092OUTSIDE/ 29092INSIDE | 双监听器 |
| Kafka UI | 9000 | kafka-ui 容器 |
| Zookeeper | 2181 | Kafka 协调 |
| Debezium Connect | 8083 | CDC connector |
| ClickHouse | 8123HTTP/ 9000TCP | 数据分析宽表 |
| Neo4j | 7474HTTP/ 7687Bolt | 知识图谱 |
| Elasticsearch | 9200HTTP/ 9300TCP | 全文检索 |
| Prometheus | 9090 | 指标采集(--web.enable-lifecycle |
| Grafana | 3000容器内**与 teacher-bff 3003 不冲突,因 teacher-bff 在 host 网络** | — | 实际部署需注意 |
| Alertmanager | 9093 | 告警 |
| Jaeger | 16686UI/ 4317OTLP gRPC/ 4318OTLP HTTP | 链路追踪 |
| node-exporter | 9100 | 主机指标host.docker.internal:9100 |
| mysqld-exporter | 9104 | MySQL 指标 |
| redis-exporter | 9121 | Redis 指标 |
| 服务 | 端口 | 说明 |
| ----------------- | --------------------------------------------------------------------------- | ------------------------------------- |
| MySQL | 3306 | 业务数据库external |
| Redis | 6379 | 缓存 + 会话 + Pub/Sub |
| Kafka | 9092OUTSIDE/ 29092INSIDE | 双监听器 |
| Kafka UI | 9000 | kafka-ui 容器 |
| Zookeeper | 2181 | Kafka 协调 |
| Debezium Connect | 8083 | CDC connector |
| ClickHouse | 8123HTTP/ 9000TCP | 数据分析宽表 |
| Neo4j | 7474HTTP/ 7687Bolt | 知识图谱 |
| Elasticsearch | 9200HTTP/ 9300TCP | 全文检索 |
| Prometheus | 9090 | 指标采集(--web.enable-lifecycle |
| Grafana | 3000容器内**与 teacher-bff 3003 不冲突,因 teacher-bff 在 host 网络** | — | 实际部署需注意 |
| Alertmanager | 9093 | 告警 |
| Jaeger | 16686UI/ 4317OTLP gRPC/ 4318OTLP HTTP | 链路追踪 |
| node-exporter | 9100 | 主机指标host.docker.internal:9100 |
| mysqld-exporter | 9104 | MySQL 指标 |
| redis-exporter | 9121 | Redis 指标 |
| Temporal | 7233 | gRPC frontendWorker 连接) |
| Temporal UI | 8085 | Temporal Web UI容器内 8080 |
| Temporal Postgres | 5433预留内部 5432 | Temporal 持久化存储(仅容器内) |
> **Grafana 端口冲突风险**Grafana 默认 3000与 teacher-bff 3003 不冲突(不同主机层),但开发环境若同主机部署需注意。建议 Grafana 改用 3030 避免混淆。
@@ -118,13 +121,14 @@
## 7. 变更记录
| 日期 | 变更 | 决策者 |
| ---------- | --------------------------------------------------------- | ------ |
| 2026-07-09 | 初始创建,登记全部 15 服务 + 基础设施端口 | coord |
| 2026-07-09 | 仲裁 admin-portal 3003 → 4003MF 配置 3000 → 4000 | coord |
| 2026-07-09 | 仲裁 push-gateway 豁免 gRPC释放 5005750058 让给 ai | coord |
| 2026-07-09 | classes 3001 标记为历史(已合并入 core-edu | coord |
| 2026-07-14 | M3 新增 config-service3011/50059ADR-026 从 iam 拆分) | coord |
| 日期 | 变更 | 决策者 |
| ---------- | ----------------------------------------------------------------- | ------ |
| 2026-07-09 | 初始创建,登记全部 15 服务 + 基础设施端口 | coord |
| 2026-07-09 | 仲裁 admin-portal 3003 → 4003MF 配置 3000 → 4000 | coord |
| 2026-07-09 | 仲裁 push-gateway 豁免 gRPC释放 5005750058 让给 ai | coord |
| 2026-07-09 | classes 3001 标记为历史(已合并入 core-edu | coord |
| 2026-07-14 | M3 新增 config-service3011/50059ADR-026 从 iam 拆分) | coord |
| 2026-07-14 | M6.5 新增 Temporal7233/UI 8085/PG 5433ADR-030 AI 工作流引擎) | coord |
---

View File

@@ -55,3 +55,8 @@ ENCRYPTION_KEY=<replace-with-base64-32-byte-aes-key>
# 生成openssl rand -hex 32
# 注意Router 和所有子图必须使用相同的密钥
ROUTER_AUTH_SECRET=<replace-with-32-char-router-auth-secret>
# ---------- Temporal ----------
# 用途Temporal PostgreSQL 存储密码
# 最小长度24 字符
TEMPORAL_POSTGRES_PASSWORD=<replace-with-24-char-temporal-password>