1. teacher-portal 登录 JSON 解析错误修复
- 根因:next.config.js rewrites /api/auth/* → gateway /api/auth/*,
但 gateway 只在 /api/v1 路由组下注册代理,/api/auth/* 返回 404 纯文本
- 修复:rewrites 映射 /api/auth/* → /api/v1/iam/*(对齐 iam controller @Controller("v1/iam"))
2. msg / data-ana 端口冲突修复
- 根因:msg env.ts PORT 默认 3006,与 data-ana(config.py http_port=3006)冲突
- 修复:msg PORT 默认 3006→3007(对齐端口分配表 msg=3007, data-ana=3006)
3. Prometheus classes-service 3001 DOWN 修复
- 根因:classes 已合并入 core-edu(P3 裁决 C1),但 prometheus.yml 仍有 classes-service scrape 配置
- 修复:从 prometheus.yml 删除 classes-service job
4. iam outbox 表 aggregate_id 列长度修复
- 根因:iam_outbox.aggregate_id VARCHAR(32),但 UUID 是 36 字符,导致 "Data too long" 错误
- 修复:DDL 中 VARCHAR(32) → VARCHAR(36);ALTER TABLE 修复现有数据库
5. 补充未搭建的监控基础设施
- docker-compose.yml 新增 Alertmanager(9093)/ Loki(3100)/ Promtail(observability profile)
- prometheus.yml alertmanager target 更新为 edu-alertmanager:9093
验证:
- TS typecheck 19 项目全部通过
- 登录链路 teacher-portal → gateway → iam 验证通过
- Prometheus targets 不再有 classes-service
- 3 个新基础设施容器(alertmanager/loki/promtail)启动成功
AI identity: trae-main(基础设施修复会话)
50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
import { z } from "zod";
|
||
|
||
/**
|
||
* msg 服务环境变量 schema。
|
||
*
|
||
* 仲裁依据:
|
||
* - G2 /readyz 多依赖检查(DB/ES/Redis/Kafka/PushGateway)
|
||
* - M2 PushGateway 软失败(PUSH_GATEWAY_URL 可选)
|
||
* - M4 HTTP POST /internal/push(豁免 gRPC)
|
||
* - REDIS_URL 可选,未配置时降级到 DB 唯一索引去重
|
||
*/
|
||
const envSchema = z.object({
|
||
PORT: z.string().default("3007"),
|
||
GRPC_PORT: z.string().default("50056"),
|
||
DATABASE_URL: z.string().url(),
|
||
REDIS_URL: z.string().url().optional(),
|
||
JWT_SECRET: z.string().optional(),
|
||
JWT_ISSUER: z.string().default("next-edu-cloud"),
|
||
KAFKA_BROKERS: z.string().default("localhost:9092"),
|
||
KAFKA_CLIENT_ID: z.string().default("msg-service"),
|
||
KAFKA_CONSUMER_GROUP_ID: z.string().default("msg-service-group"),
|
||
ES_URL: z.string().url().optional(),
|
||
PUSH_GATEWAY_URL: z.string().url().optional(),
|
||
PUSH_INTERNAL_TOKEN: z.string().optional(),
|
||
OTEL_EXPORTER_OTLP_ENDPOINT: z.string().url().optional(),
|
||
LOG_LEVEL: z
|
||
.enum(["fatal", "error", "warn", "info", "debug", "trace"])
|
||
.default("info"),
|
||
NODE_ENV: z
|
||
.enum(["development", "production", "test"])
|
||
.default("development"),
|
||
DEV_MODE: z.string().optional().default("false"),
|
||
});
|
||
|
||
export type Env = z.infer<typeof envSchema>;
|
||
|
||
export function loadEnv(): Env {
|
||
const result = envSchema.safeParse(process.env);
|
||
if (!result.success) {
|
||
console.error(
|
||
"❌ Invalid environment variables:",
|
||
result.error.flatten().fieldErrors,
|
||
);
|
||
throw new Error("Invalid environment configuration");
|
||
}
|
||
return result.data;
|
||
}
|
||
|
||
export const env = loadEnv();
|