Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dc04a2671 | ||
|
|
f5994ad77e | ||
|
|
3cc00de8f6 |
@@ -24,7 +24,7 @@
|
||||
<!-- gitnexus:start -->
|
||||
# GitNexus — Code Intelligence
|
||||
|
||||
This project is indexed by GitNexus as **a-share-analysis** (879 symbols, 1062 relationships, 23 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||
This project is indexed by GitNexus as **a-share-analysis** (958 symbols, 1141 relationships, 23 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||
|
||||
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
|
||||
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
本项目采用语义化版本。功能级变化请从 `docs/features/` 按功能编号追溯。
|
||||
|
||||
## 0.0.7 - 2026-08-13
|
||||
|
||||
- 将项目唯一消息队列技术基线由 RabbitMQ 调整为 RocketMQ 5.x。
|
||||
- 建立 MessageBusAdapter、Topic/Group、重试、死信和顺序消息约束。
|
||||
- 更新 Scheduler/Worker 环境模板和双部署文档,并记录本机 NameServer 分层连接验证。
|
||||
|
||||
## 0.0.6 - 2026-08-13
|
||||
|
||||
- 建立上一发布版本开发数据库 Schema 基线生成、规范化和自动校验工具。
|
||||
|
||||
@@ -10,7 +10,7 @@ A read-only A-share market overview and analysis tool.
|
||||
|
||||
- `web/`: Vue 3 market terminal frontend.
|
||||
- `server/`: NestJS API, scheduler, and workers. Added in a later module.
|
||||
- `deploy/`: MySQL, Redis, and RabbitMQ deployment configuration. Added with the backend module.
|
||||
- `deploy/`: MySQL 5.7, Redis, and RocketMQ 5.x deployment configuration. Added with the backend module.
|
||||
- `docs/`: Product and implementation specifications.
|
||||
|
||||
The first implementation slice is the market overview screen in `web/`.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"format_version": 1,
|
||||
"status": "not_applicable",
|
||||
"application_version": "v0.0.6",
|
||||
"git_commit": "70f020f87c0cf9e19512581d798a3491c9aae5f6",
|
||||
"source_environment": "development",
|
||||
"database_name": "a_share_analysis_dev",
|
||||
"mysql_client_version": "not_enabled",
|
||||
"mysqldump_client_version": "not_enabled",
|
||||
"mysql_server_version": "not_enabled",
|
||||
"charset": "utf8mb4",
|
||||
"collation": "utf8mb4_general_ci",
|
||||
"generated_at": "2026-08-13T05:58:53.506Z",
|
||||
"generator": "schema-baseline/1.0.0",
|
||||
"reason": "mysql_disabled",
|
||||
"schema_sha256": "not_applicable",
|
||||
"objects": {
|
||||
"tables": false,
|
||||
"views": false,
|
||||
"triggers": false,
|
||||
"routines": false,
|
||||
"events": false
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -11,8 +11,9 @@ REDIS_PASSWORD=
|
||||
REDIS_DATABASE=1
|
||||
REDIS_TLS=false
|
||||
|
||||
# 第一阶段关闭 RabbitMQ,任务通过服务内 Adapter 调用。
|
||||
RABBITMQ_ENABLED=false
|
||||
RABBITMQ_URL=
|
||||
RABBITMQ_EXCHANGE=a-share-analysis
|
||||
RABBITMQ_PREFETCH=10
|
||||
# 第一阶段关闭 RocketMQ,任务通过服务内 MessageBusAdapter 调用。
|
||||
ROCKETMQ_ENABLED=false
|
||||
ROCKETMQ_NAMESRV_ADDR=127.0.0.1:9876
|
||||
ROCKETMQ_ENDPOINT=127.0.0.1:8081
|
||||
ROCKETMQ_TOPIC_PREFIX=a-share-analysis
|
||||
ROCKETMQ_SEND_TIMEOUT_MS=3000
|
||||
|
||||
+6
-4
@@ -22,10 +22,12 @@ MYSQL_PASSWORD=
|
||||
MYSQL_CHARSET=utf8mb4
|
||||
MYSQL_COLLATION=utf8mb4_general_ci
|
||||
|
||||
RABBITMQ_ENABLED=false
|
||||
RABBITMQ_URL=
|
||||
RABBITMQ_EXCHANGE=a-share-analysis
|
||||
RABBITMQ_PREFETCH=10
|
||||
ROCKETMQ_ENABLED=false
|
||||
ROCKETMQ_NAMESRV_ADDR=127.0.0.1:9876
|
||||
ROCKETMQ_ENDPOINT=127.0.0.1:8081
|
||||
ROCKETMQ_TOPIC_PREFIX=a-share-analysis
|
||||
ROCKETMQ_CONSUMER_GROUP=a-share-analysis-worker
|
||||
ROCKETMQ_CONSUMER_CONCURRENCY=4
|
||||
|
||||
AI_ENABLED=false
|
||||
AI_BASE_URL=
|
||||
|
||||
+5
-4
@@ -10,7 +10,8 @@ REDIS_PASSWORD=
|
||||
REDIS_DATABASE=1
|
||||
REDIS_TLS=false
|
||||
|
||||
RABBITMQ_ENABLED=false
|
||||
RABBITMQ_URL=
|
||||
RABBITMQ_EXCHANGE=a-share-analysis
|
||||
RABBITMQ_PREFETCH=10
|
||||
ROCKETMQ_ENABLED=false
|
||||
ROCKETMQ_NAMESRV_ADDR=
|
||||
ROCKETMQ_ENDPOINT=
|
||||
ROCKETMQ_TOPIC_PREFIX=a-share-analysis
|
||||
ROCKETMQ_SEND_TIMEOUT_MS=3000
|
||||
|
||||
+6
-4
@@ -22,10 +22,12 @@ MYSQL_PASSWORD=
|
||||
MYSQL_CHARSET=utf8mb4
|
||||
MYSQL_COLLATION=utf8mb4_general_ci
|
||||
|
||||
RABBITMQ_ENABLED=false
|
||||
RABBITMQ_URL=
|
||||
RABBITMQ_EXCHANGE=a-share-analysis
|
||||
RABBITMQ_PREFETCH=10
|
||||
ROCKETMQ_ENABLED=false
|
||||
ROCKETMQ_NAMESRV_ADDR=
|
||||
ROCKETMQ_ENDPOINT=
|
||||
ROCKETMQ_TOPIC_PREFIX=a-share-analysis
|
||||
ROCKETMQ_CONSUMER_GROUP=a-share-analysis-worker
|
||||
ROCKETMQ_CONSUMER_CONCURRENCY=4
|
||||
|
||||
AI_ENABLED=false
|
||||
AI_BASE_URL=
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# ADR-0003:采用 RocketMQ 5.x 作为唯一消息队列
|
||||
|
||||
- 状态:accepted
|
||||
- 日期:2026-08-13
|
||||
- 关联功能:GOV-008
|
||||
|
||||
## 背景
|
||||
|
||||
项目此前在架构和环境模板中约定 RabbitMQ,但尚未实现消息客户端、Topic 或业务消费流程。产品需要分钟级盘中分析、定时采集、指标计算、AI 分析和失败重试,决定在实现前统一切换到 RocketMQ。
|
||||
|
||||
## 决策
|
||||
|
||||
- 项目唯一消息队列为 RocketMQ 5.x,不维护 RabbitMQ 双栈。
|
||||
- Scheduler 和 Worker 只依赖项目级 `MessageBusAdapter` 与版本化事件契约。
|
||||
- Node.js 客户端优先通过 RocketMQ 5.x Proxy 接入;若改用直接 NameServer/Broker 客户端,必须通过兼容性和可靠性验证。
|
||||
- Topic、Tag、Producer Group、Consumer Group、顺序键、重试与死信语义必须在功能设计中明确。
|
||||
- 本地和生产基础设施独立于应用发布;NameServer、Broker、Proxy 不随应用版本自动创建或删除。
|
||||
|
||||
## 原因
|
||||
|
||||
RocketMQ 对定时/延迟任务、重试、死信、顺序消息和后续任务规模扩展更符合预期。Adapter 边界用于控制 Node 客户端成熟度和接入协议变化带来的风险。
|
||||
|
||||
## 代价
|
||||
|
||||
- 本地和生产运维复杂度高于单节点 RabbitMQ,需要区分 NameServer、Broker 和 Proxy。
|
||||
- Node.js 生态需要在 Server 脚手架阶段单独验证,不能仅凭 NameServer 端口可达决定客户端可用。
|
||||
- 所有消费者必须按至少一次投递设计幂等和受控重放。
|
||||
|
||||
## 验证
|
||||
|
||||
GOV-008 只验证配置、文档契约和本机 NameServer 状态。真实 Topic 生产/消费必须在 Broker/Proxy 可用且 Server 客户端选定后补充契约测试。
|
||||
@@ -7,8 +7,8 @@
|
||||
```text
|
||||
web/ Vue 3 前端
|
||||
server/ NestJS API、Scheduler 与 Worker
|
||||
contracts/ HTTP 与 RabbitMQ 版本化契约
|
||||
deploy/ MySQL、Redis、RabbitMQ 和运行配置
|
||||
contracts/ HTTP 与 RocketMQ 版本化契约
|
||||
deploy/ MySQL、Redis、RocketMQ 5.x 和运行配置
|
||||
docs/ 规范、架构、ADR 与功能档案
|
||||
tools/ 可重复执行的治理和开发工具
|
||||
```
|
||||
@@ -20,7 +20,8 @@ tools/ 可重复执行的治理和开发工具
|
||||
```text
|
||||
免费数据源
|
||||
→ Scheduler 定时投递
|
||||
→ RabbitMQ
|
||||
→ MessageBusAdapter
|
||||
→ RocketMQ 5.x
|
||||
→ 行情采集 Worker
|
||||
→ 指标计算 Worker
|
||||
→ 规则 / AI / 混合分析
|
||||
@@ -30,7 +31,8 @@ tools/ 可重复执行的治理和开发工具
|
||||
```
|
||||
|
||||
- Scheduler只负责触发时间。
|
||||
- RabbitMQ只负责任务传递、确认、重试和死信。
|
||||
- MessageBusAdapter 隔离业务与 RocketMQ 客户端,禁止业务模块直接依赖 SDK。
|
||||
- RocketMQ 只负责任务传递、确认、重试、延迟消息和死信;重复投递由 Worker 幂等处理。
|
||||
- Worker负责采集、标准化、计算和分析。
|
||||
- MySQL保存可追溯事实与历史报告。
|
||||
- Redis保存最新快照、缓存、锁和限流状态。
|
||||
@@ -52,7 +54,7 @@ tools/ 可重复执行的治理和开发工具
|
||||
|
||||
- 应用运行环境只定义 `development` 与 `production`;生产环境禁止模拟数据、热更新、调试端口和开发默认值回退。
|
||||
- API、Scheduler、Worker、Web 分别拥有开发和生产模板;同一进程跨环境使用相同变量名,通过启动 Schema 校验条件必填项。
|
||||
- 本地开发使用 Docker Compose 只启动 Redis,应用进程从源码运行;第一阶段 MySQL 与 RabbitMQ 保持关闭。
|
||||
- 本地开发使用 Docker Compose 只启动 Redis,应用进程从源码运行;第一阶段 MySQL 与 RocketMQ 保持关闭。需要联调时可以连接本机独立运行的 RocketMQ 5.x。
|
||||
- 生产同时支持 Docker Compose 和 Ubuntu 22.04/24.04 LTS x86_64 源码部署,两者共用配置契约和进程边界。
|
||||
- 源码部署由管理员预装 Node.js 22 LTS、pnpm 10、Nginx 和基础设施;项目只验证,不安装或修改系统软件源。
|
||||
- 源码部署使用不可变发布目录、`a-share` 用户和 systemd 独立进程配置;生产 env 存放在 `/etc/a-share-analysis/`,不随代码版本切换覆盖。
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
- 从 `deploy/env/production/` 准备四份真实配置,存放在服务器 `/etc/a-share-analysis/` 或其他受控目录。
|
||||
- Compose 通过外部路径加载,不在 YAML、镜像和 Git 中保存秘密。
|
||||
- 镜像引用必须包含版本或内容摘要,禁止浮动 `latest`。
|
||||
- 第一阶段只依赖 Redis;MySQL 和 RabbitMQ 功能开关保持关闭。
|
||||
- 第一阶段只依赖 Redis;MySQL 和 RocketMQ 5.x 功能开关保持关闭。
|
||||
- 启用 RocketMQ 时优先连接受运维管理的外部集群或独立基础设施 Compose,不把 NameServer、Broker、Proxy 混入应用发布生命周期。
|
||||
|
||||
## 发布与回退
|
||||
|
||||
部署前验证镜像对应已推送提交或标签、环境 Schema、健康检查和数据目录。升级只修改不可变镜像引用;失败时恢复上一完整镜像集合和未改变的外部配置。禁止删除 Redis、MySQL 或 RabbitMQ 数据目录作为应用回退手段。
|
||||
部署前验证镜像对应已推送提交或标签、环境 Schema、健康检查和数据目录。升级只修改不可变镜像引用;失败时恢复上一完整镜像集合和未改变的外部配置。禁止删除 Redis、MySQL 或 RocketMQ CommitLog 数据目录作为应用回退手段。
|
||||
|
||||
## 验证
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 本地开发环境
|
||||
|
||||
本地开发使用 Docker Compose 只启动 Redis,Web、API、Scheduler 和 Worker 从源码运行并使用开发环境模板。第一阶段不启动 MySQL 和 RabbitMQ。
|
||||
本地开发使用 Docker Compose 只启动 Redis,Web、API、Scheduler 和 Worker 从源码运行并使用开发环境模板。第一阶段不自动启动 MySQL 和 RocketMQ 5.x。
|
||||
|
||||
## 配置
|
||||
|
||||
@@ -16,6 +16,12 @@ docker compose -f deploy/compose/development.yml down
|
||||
|
||||
Redis 只绑定 `127.0.0.1:6379`,数据写入仓库忽略的 `.local/redis/`。不得把该 Compose 文件用于生产。
|
||||
|
||||
## RocketMQ 联调
|
||||
|
||||
RocketMQ 由开发者在项目 Compose 外独立启动。应用启用前至少需要 NameServer、Broker;采用推荐的 Node.js Proxy 接入时还需要 Proxy。默认端口约定:NameServer `9876`、Broker `10911`、Proxy gRPC `8081`。
|
||||
|
||||
`nc -vz 127.0.0.1 9876` 只能证明 NameServer TCP 可达,不能证明 Topic 路由、Broker 注册或消息收发可用。完整联调必须继续检查 Broker 列表,并执行一次测试 Topic 的生产与消费。开发模板默认 `ROCKETMQ_ENABLED=false`;启用后必须提供可用的 `ROCKETMQ_ENDPOINT`,不得把生产地址写入本地配置或仓库。
|
||||
|
||||
## 应用状态
|
||||
|
||||
Web 和 Server 尚未完成脚手架,因此本版本只交付配置契约和 Redis 开发环境。后续脚手架必须使用 Node.js 22 LTS、pnpm 10 和这些模板,不能在本文档中假装应用已经可启动。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Ubuntu 源码生产部署
|
||||
|
||||
正式支持 Ubuntu 22.04 LTS 与 Ubuntu 24.04 LTS 的 x86_64。服务器管理员预先提供 Node.js 22 LTS、pnpm 10、Nginx,以及 MySQL 5.7、Redis、RabbitMQ 或相应外部服务;项目不负责安装或升级这些软件,也不修改系统软件源。
|
||||
正式支持 Ubuntu 22.04 LTS 与 Ubuntu 24.04 LTS 的 x86_64。服务器管理员预先提供 Node.js 22 LTS、pnpm 10、Nginx,以及 MySQL 5.7、Redis、RocketMQ 5.x 或相应外部服务;项目不负责安装或升级这些软件,也不修改系统软件源。
|
||||
|
||||
## 前置验证
|
||||
|
||||
@@ -33,3 +33,5 @@ nginx -v
|
||||
在新的不可变发布目录完成安装、构建和配置校验后,原子切换 `current`,依次重启 API、Scheduler、Worker 并检查 `systemctl status`、`journalctl` 和 HTTP 健康端点。失败时切回上一完整目录并重启服务;生产配置不随版本切换覆盖。
|
||||
|
||||
项目部署流程禁止连接或读取生产数据库做开发验证。数据库备份属于独立运维职责,应用回退不得删除或覆盖数据。
|
||||
|
||||
RocketMQ 由运维独立维护 NameServer、Broker 和需要时的 Proxy。应用发布只读取受控的 RocketMQ Endpoint、Topic 前缀与 Group 配置,不负责创建或升级集群,也不得把 Broker 数据目录放进应用发布目录。
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
## 非目标
|
||||
|
||||
- 不做自选股、持仓、笔记、交易计划、社区、荐股、跟单和公开组合。
|
||||
- 本切片不接正式行情源、RabbitMQ、MySQL、Redis和付费 AI。
|
||||
- 本切片不接正式行情源、RocketMQ、MySQL、Redis和付费 AI。
|
||||
- 本切片不实现用户、邀请、会员、订阅和支付。
|
||||
- ETF监控、两融数据、大盘云图和实时消息仍是独立一级模块。
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# RocketMQ 消息队列架构调整设计
|
||||
|
||||
- 功能编号:GOV-008
|
||||
- 设计版本:0.1
|
||||
- 状态:approved
|
||||
- 日期:2026-08-13
|
||||
|
||||
## 架构
|
||||
|
||||
```text
|
||||
Scheduler
|
||||
-> MessageBusAdapter.publish()
|
||||
-> RocketMQ 5.x Proxy 或受支持客户端
|
||||
-> NameServer / Broker
|
||||
-> MessageBusAdapter.consume()
|
||||
-> Worker
|
||||
-> Redis 当前状态 + MySQL 事实记录
|
||||
```
|
||||
|
||||
`MessageBusAdapter` 是稳定边界。业务消息、Topic 和 Group 不引用 RocketMQ SDK 类型,未来客户端实现变化不要求重写调度与分析逻辑。项目只维护 RocketMQ 一套实现,不同时维护 RabbitMQ 兼容层。
|
||||
|
||||
## 接入模式
|
||||
|
||||
推荐 Node.js 通过 RocketMQ 5.x Proxy 接入,以降低对旧 Remoting 客户端实现的依赖。若后续选定的 Node 客户端直接连接 NameServer/Broker,必须先验证客户端维护状态、RocketMQ 5.3.2 兼容性、重试语义和优雅关闭,再通过 Adapter 接入。
|
||||
|
||||
`ROCKETMQ_NAMESRV_ADDR` 用于基础设施发现和诊断,`ROCKETMQ_ENDPOINT` 是应用客户端实际接入地址。两者不得混为同一项:只有 NameServer 端口可达时,不能完成生产或消费。
|
||||
|
||||
## Topic 与 Group
|
||||
|
||||
- Topic 前缀固定为 `a-share-analysis`,实际 Topic 按业务域追加,例如行情采集或指标计算。
|
||||
- Tag 使用稳定事件类型,不用临时任务 ID。
|
||||
- RocketMQ 5.x Proxy Producer 不配置 Producer Group;Worker 按独立消费语义使用 Consumer Group。
|
||||
- 环境隔离通过受控前缀或独立集群完成,禁止开发消费者读取生产 Topic。
|
||||
|
||||
## 可靠性
|
||||
|
||||
RocketMQ 提供至少一次投递语义,Worker 必须幂等。消息处理完成并形成可验证结果后才能确认;可重试错误返回重试,永久错误记录原因后进入死信。顺序消息只在明确消息组键内保证,不假设跨证券或跨交易日全局顺序。
|
||||
|
||||
最大投递次数是 Consumer Group 的服务端重试策略,由 RocketMQ 运维配置和发布检查负责。应用客户端只声明 Consumer Group、并发与处理结果,不能用一个不会被官方 Node SDK读取的 env 字段假装控制死信边界。
|
||||
|
||||
## 本地状态
|
||||
|
||||
2026-08-13 首次检查到 `apache/rocketmq:5.3.2` 的 `rmqnamesrv` 容器曾运行并映射 `9876:9876`,日志为 NameServer boot success;随后串行复核发现该容器已以 137 退出且未配置自动重启,`OOMKilled=false`。
|
||||
|
||||
宿主机 `9876` 实际由 `/usr/local/rocketmq` 的原生 NameServer 监听,同时存在 `mqbroker --enable-proxy`。只读 `mqadmin` 验证结果:`broker-a` 已注册,版本 `V5_3_2`、`brokerActive=true`,Broker 地址 `192.168.2.37:10911`;本机 `10911`、Proxy `8081` 和 NameServer `9876` 均可达,Topic 列表可读取。当前可确认 RocketMQ 基础设施和管理链路连通,但尚未通过项目 Node 客户端执行消息收发。
|
||||
@@ -0,0 +1,22 @@
|
||||
# GitNexus 开发后基线
|
||||
|
||||
## 状态
|
||||
|
||||
```text
|
||||
Repository: /Users/citrons/Documents/Codex/2026-08-12/wo-x/a-share-analysis
|
||||
Indexed: 8/13/2026, 2:23:20 PM
|
||||
Indexed commit: f5994ad
|
||||
Current commit: f5994ad
|
||||
Status: ✅ up-to-date
|
||||
```
|
||||
|
||||
## 图谱规模
|
||||
|
||||
- 958 个节点。
|
||||
- 1141 条关系。
|
||||
- 13 个聚类。
|
||||
- 23 条流程。
|
||||
|
||||
本次新增内容以文档、环境模板和契约测试为主,没有新增 MQ 运行时代码或执行流。
|
||||
|
||||
最终实现提交 `f5994ad77ec980175f671475e82c72d9d7e6f979` 已推送 `origin/main`,实时远程 SHA 核对一致。
|
||||
@@ -0,0 +1,26 @@
|
||||
# GitNexus 开发前基线
|
||||
|
||||
- 功能编号:GOV-008
|
||||
- 记录时间:2026年8月13日 GMT+8 13:59:16
|
||||
- 分支:main
|
||||
- 基线提交:3cc00de8f65e
|
||||
|
||||
## 工作区
|
||||
|
||||
```text
|
||||
(干净)
|
||||
```
|
||||
|
||||
## GitNexus 状态
|
||||
|
||||
```text
|
||||
Repository: /Users/citrons/Documents/Codex/2026-08-12/wo-x/a-share-analysis
|
||||
Indexed: 8/13/2026, 1:59:15 PM
|
||||
Indexed commit: 3cc00de
|
||||
Current commit: 3cc00de
|
||||
Status: ✅ up-to-date
|
||||
```
|
||||
|
||||
## 后续人工分析
|
||||
|
||||
在修改代码前,将 GitNexus query、context、impact 的结论写入 `gitnexus/impact-plan.md`。高风险结果必须先获得用户确认。
|
||||
@@ -0,0 +1,14 @@
|
||||
# GitNexus 前后对比
|
||||
|
||||
## 开发前
|
||||
|
||||
- 基线提交:`3cc00de`
|
||||
- RabbitMQ 仅存在于文档、模板和契约测试,没有运行时代码或执行流。
|
||||
|
||||
## 开发后
|
||||
|
||||
- 当前活动架构统一为 RocketMQ 5.x。
|
||||
- 新增 MessageBusAdapter、Topic/Tag/Group、重试、死信、幂等和顺序键约束。
|
||||
- GitNexus 变更检测为 LOW,0 条执行流受影响。
|
||||
|
||||
结论:调整发生在实现客户端之前,避免了双栈迁移;后续真实风险集中在 Node 客户端与 RocketMQ 5.3.2 的契约验证。
|
||||
@@ -0,0 +1,10 @@
|
||||
# GitNexus 变更检测
|
||||
|
||||
- 检测日期:2026-08-13
|
||||
- 范围:unstaged
|
||||
- 变更文件:16 个已跟踪文件,另含 GOV-008 功能档案与 ADR 新文件。
|
||||
- 变更符号:35
|
||||
- 受影响流程:0
|
||||
- 风险:LOW
|
||||
|
||||
变更集中在当前架构、环境模板、部署说明、代码规范和环境契约测试。GitNexus 未发现市场业务、数据库、HTTP 或消息运行流程受影响,因为 Server 和 MQ 客户端尚未实现。
|
||||
@@ -0,0 +1,13 @@
|
||||
# GitNexus 开发前影响分析
|
||||
|
||||
- 分析日期:2026-08-13
|
||||
- 基线提交:`3cc00de`
|
||||
- 索引状态:up-to-date
|
||||
|
||||
查询 RabbitMQ、消息队列、Scheduler、Worker 和部署配置。当前仓库没有 Server 生产代码或 MQ 执行流,影响集中在系统架构、代码开发规范、环境模板、部署文档和环境契约测试。
|
||||
|
||||
- `environment-baseline.test.mjs`:LOW,无上游调用方或业务流程。
|
||||
- `system-architecture.md`:LOW,直接引用方为 README 与文档索引。
|
||||
- `code-development-standards.md`:LOW,直接引用方为 README 与文档索引。
|
||||
|
||||
结论:不影响市场业务、数据库或 HTTP 运行流程。主要风险是环境键漂移和把 NameServer 可达误判为消息链路可用,分别由契约测试和分层连接证据控制。
|
||||
@@ -0,0 +1,13 @@
|
||||
# GOV-008 实施计划
|
||||
|
||||
- [x] 封存并推送 `v0.0.6` 开发库 N/A Schema 基线。
|
||||
- [x] 执行 `governance:start` 与 GitNexus 开发前探索和影响分析。
|
||||
- [x] 先修改环境契约测试,确认旧 RabbitMQ 配置使测试失败。
|
||||
- [x] 将 Scheduler/Worker 开发和生产模板改为 `ROCKETMQ_*`。
|
||||
- [x] 更新系统架构、代码开发规范、部署文档和未发布市场概览 PRD。
|
||||
- [x] 补齐 GOV-008 功能档案和本机连接验证证据。
|
||||
- [x] 运行治理、MySQL、环境、Schema 测试和配置/文档检查。
|
||||
- [x] 执行 GitNexus 变更检测、代码 Review 与规范 Review。
|
||||
- [x] 执行 `governance:finish`,中文提交并推送 Gitea。
|
||||
|
||||
本版本不实现客户端、不创建 Broker/Proxy、不发送测试消息。后续 Server 脚手架功能负责选型 Node 客户端并完成真实 Topic 收发契约测试。
|
||||
@@ -0,0 +1,18 @@
|
||||
id: GOV-008
|
||||
name: RocketMQ 消息队列架构调整
|
||||
slug: rocketmq-adoption
|
||||
status: released
|
||||
owner: project
|
||||
created_at: 2026-08-13
|
||||
prd: prd.md
|
||||
requirements: requirements.md
|
||||
design: design.md
|
||||
implementation_plan: implementation-plan.md
|
||||
test_plan: test-plan.md
|
||||
gitnexus_before: gitnexus/before.md
|
||||
gitnexus_after: gitnexus/after.md
|
||||
gitnexus_comparison: gitnexus/comparison.md
|
||||
code_review: review/code-review.md
|
||||
standards_review: review/standards-review.md
|
||||
implementation_commit: f5994ad77ec980175f671475e82c72d9d7e6f979
|
||||
release: v0.0.7
|
||||
@@ -0,0 +1,33 @@
|
||||
# RocketMQ 消息队列架构调整 PRD
|
||||
|
||||
- 功能编号:GOV-008
|
||||
- PRD 版本:0.1
|
||||
- 状态:approved
|
||||
- 日期:2026-08-13
|
||||
|
||||
## 问题
|
||||
|
||||
项目早期约定 RabbitMQ,但尚未实现消息客户端或业务消息链路。现决定统一采用 RocketMQ,并需要在服务脚手架落地前同步架构、环境契约和部署边界,避免后续同时维护两套消息模型。
|
||||
|
||||
## 目标
|
||||
|
||||
- 项目唯一消息队列调整为 RocketMQ 5.x。
|
||||
- Scheduler 和 Worker 通过 `MessageBusAdapter` 使用版本化消息契约。
|
||||
- 配置明确区分 NameServer、Broker/Proxy Endpoint、Topic 和 Group。
|
||||
- 保留本地默认关闭策略,同时允许连接独立运行的本机 RocketMQ。
|
||||
- 检查当前本机 Docker RocketMQ 的实际连通状态,不夸大验证范围。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 本版本不实现 Server、Scheduler、Worker 或 RocketMQ Node 客户端。
|
||||
- 不替用户创建、删除或重启 Docker 或本机 RocketMQ 进程。
|
||||
- 不连接生产 RocketMQ,不创建生产 Topic 或 Group。
|
||||
- NameServer 可达时不宣称消息生产和消费已经可用。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- 当前架构、开发规范、部署说明和环境模板只采用 RocketMQ。
|
||||
- Scheduler 与 Worker 开发/生产模板键集合分别一致,且无 RabbitMQ 变量。
|
||||
- 文档定义重复投递、幂等、重试、死信和顺序消息边界。
|
||||
- 本机 NameServer 的版本、端口和启动状态有可复核证据。
|
||||
- 诊断必须区分 Docker 容器与本机原生进程,并报告 NameServer、Broker、Proxy 的真实状态。
|
||||
@@ -0,0 +1,19 @@
|
||||
# 测试结果
|
||||
|
||||
- 日期:2026-08-13
|
||||
- 状态:passed
|
||||
|
||||
测试先行阶段,环境契约测试按预期因缺少 `ROCKETMQ_*` 和活动文档仍包含 RabbitMQ 而失败。实现后结果:
|
||||
|
||||
- 治理测试:5/5 passed。
|
||||
- MySQL 5.7 基线测试:2/2 passed。
|
||||
- 环境与部署契约测试:7/7 passed。
|
||||
- Schema 基线测试:23/23 passed。
|
||||
- `npm run schema:verify`:`v0.0.6 (not_applicable)` passed。
|
||||
- `git diff --check` 与 Node 语法检查:passed。
|
||||
- 活动架构、部署、治理规范与环境模板 RabbitMQ 残留扫描:passed。
|
||||
- `npm run governance:finish -- GOV-008 rocketmq-adoption`:passed。
|
||||
- 独立代码 Review 与开发规范 Review:passed。
|
||||
- 最终实现提交:`f5994ad77ec980175f671475e82c72d9d7e6f979`,已推送 `origin/main`。
|
||||
|
||||
本机诊断确认:Docker `rmqnamesrv` 容器曾启动成功但现已以 137 退出,且非 OOM;宿主机原生 RocketMQ 5.3.2 正在运行 NameServer、`broker-a` 和 Proxy。`9876`、`10911`、`8081` 可达,`mqadmin` 可读取集群、Topic 和 Broker 状态。项目 Node 客户端尚未实现,因此未创建 Topic 或写入测试消息。
|
||||
@@ -0,0 +1,5 @@
|
||||
# 视觉 QA
|
||||
|
||||
本功能没有页面、组件、样式或浏览器交互变化,视觉 QA 不适用。
|
||||
|
||||
结论:not_applicable
|
||||
@@ -0,0 +1,7 @@
|
||||
# 发布说明
|
||||
|
||||
- 项目消息队列技术基线由 RabbitMQ 调整为 RocketMQ 5.x。
|
||||
- Scheduler 和 Worker 配置切换为 `ROCKETMQ_*`,并明确 Topic、Group、重试和接入地址。
|
||||
- 增加 `MessageBusAdapter` 边界,避免业务绑定具体客户端。
|
||||
- 本机原生 RocketMQ 5.3.2 NameServer、Broker 和 Proxy 已验证可达,Broker 已注册且状态正常;Docker `rmqnamesrv` 容器已退出,项目消息收发待 Node 客户端落地后验证。
|
||||
- 最终实现提交:`f5994ad77ec980175f671475e82c72d9d7e6f979`。
|
||||
@@ -0,0 +1,29 @@
|
||||
# 工程需求
|
||||
|
||||
## 技术基线
|
||||
|
||||
- MQ 固定为 RocketMQ 5.x,当前本机镜像版本为 `apache/rocketmq:5.3.2`。
|
||||
- 业务模块只依赖 `MessageBusAdapter` 与版本化事件,不直接引用客户端 SDK 类型。
|
||||
- Scheduler 只发布任务,Worker 只消费执行;重复投递由幂等键和业务唯一约束处理。
|
||||
|
||||
## 配置契约
|
||||
|
||||
- Scheduler 使用 `ROCKETMQ_ENABLED`、`ROCKETMQ_NAMESRV_ADDR`、`ROCKETMQ_ENDPOINT`、`ROCKETMQ_TOPIC_PREFIX` 和发送超时。RocketMQ 5.x Proxy 官方 Node Producer 不要求 Producer Group,禁止把旧 Remoting 参数混入配置。
|
||||
- Worker 使用相同的基础连接字段,并增加 `ROCKETMQ_CONSUMER_GROUP` 和客户端消费并发。
|
||||
- 开发和生产模板的同一进程必须保持相同键集合;生产连接地址留空且不得提交真实值。
|
||||
- `ROCKETMQ_ENABLED=false` 时不建立连接;启用后 Endpoint、Topic 和对应 Group 必须通过启动配置 Schema 校验。
|
||||
|
||||
## 消息语义
|
||||
|
||||
- 事件必须包含 `eventId`、`eventType`、`schemaVersion`、`occurredAt`、`tradeDate`、`traceId` 和 `idempotencyKey`。
|
||||
- Topic 表达稳定业务域,Tag 表达事件类型,Consumer Group 表达独立消费进度。
|
||||
- 需要顺序处理时必须声明消息组键;普通消息不保证全局顺序。
|
||||
- 超过最大消费次数后进入死信,必须支持查询、告警和受控重放。
|
||||
- 最大投递次数属于 RocketMQ 服务端 Consumer Group 重试策略,由运维配置并纳入部署验收,不作为官方 Node PushConsumer 的客户端环境变量。
|
||||
|
||||
## 本机验证
|
||||
|
||||
- 检查容器、镜像、端口映射和 NameServer 启动日志。
|
||||
- 使用 TCP 探针验证 `127.0.0.1:9876`。
|
||||
- 检查 Docker 容器和本机原生进程,避免把相同端口的其他监听者误判为目标容器。
|
||||
- 通过 `mqadmin clusterList`、`topicList`、`brokerStatus` 确认 Broker 注册、版本和管理链路;不擅自创建 Topic 或写入测试消息。
|
||||
@@ -0,0 +1,22 @@
|
||||
# 代码 Review
|
||||
|
||||
## 第一轮
|
||||
|
||||
结论:changes_required。发现 2 个 Important:配置混入旧 Remoting Producer Group 和无效的客户端最大重试字段;RabbitMQ 残留断言只覆盖生产 Worker。
|
||||
|
||||
## 处置
|
||||
|
||||
- 删除 `ROCKETMQ_PRODUCER_GROUP` 和 `ROCKETMQ_MAX_RECONSUME_TIMES`。
|
||||
- 明确最大投递次数属于服务端 Consumer Group 运维策略。
|
||||
- 扩展测试覆盖 Scheduler/Worker 的开发与生产四份模板,同时核对开发和生产连接地址边界。
|
||||
|
||||
## 最终复审
|
||||
|
||||
- 四份 Scheduler/Worker 模板均移除旧 RabbitMQ 字段、旧 Remoting Producer Group 和无效的客户端最大重试字段。
|
||||
- 开发模板统一使用 `127.0.0.1:9876` 和 `127.0.0.1:8081` 且保持关闭;生产连接地址保持空值。
|
||||
- 最大投递次数归属服务端 Consumer Group 运维策略,文档和配置语义一致。
|
||||
- 环境 7/7、治理 5/5、MySQL 2/2、Schema 23/23 及 Schema 验证通过。
|
||||
|
||||
Critical、Important、Minor 均无未关闭项。
|
||||
|
||||
最终结论:passed
|
||||
@@ -0,0 +1,12 @@
|
||||
# 开发规范符合性 Review
|
||||
|
||||
## 检查结果
|
||||
|
||||
- PRD、需求、设计、实施计划、测试计划、回退和 GitNexus 档案齐全。
|
||||
- 技术基线统一为 RocketMQ 5.x,历史档案保留原版本事实。
|
||||
- 配置模板无秘密,开发与生产同进程键集合一致,生产连接地址为空。
|
||||
- Node.js 接入边界明确采用 MessageBusAdapter,未提前绑定未经验证的 SDK 参数。
|
||||
- 本机诊断只读执行,未创建 Topic、未发送消息、未修改或重启用户进程。
|
||||
- 测试先行、GitNexus 影响分析和独立复审证据齐全。
|
||||
|
||||
最终结论:passed
|
||||
@@ -0,0 +1,7 @@
|
||||
# 回退说明
|
||||
|
||||
本功能只修改架构约定、无秘密环境模板、文档和契约测试,没有启动、停止或修改用户的 Docker 容器,也没有连接生产服务。
|
||||
|
||||
若后续 RocketMQ 客户端验证失败,使用新的治理功能和中文提交调整 Adapter 实现或接入方式;不得在业务代码中临时绕过 Adapter。回退文档配置时可以恢复上一已发布提交,但必须同步恢复开发/生产模板和契约测试,禁止形成一半 RabbitMQ、一半 RocketMQ 的混合状态。
|
||||
|
||||
本机 `rmqnamesrv` 容器及其 Docker 网络属于用户环境,不由仓库回退操作管理。
|
||||
@@ -0,0 +1,19 @@
|
||||
# 测试计划
|
||||
|
||||
## 自动化
|
||||
|
||||
- 开发和生产同进程环境键一致。
|
||||
- 生产模板禁止模拟数据并保持 MySQL 5.7 与 RocketMQ 开关契约。
|
||||
- 活动架构和部署文档包含 RocketMQ 且不再包含 RabbitMQ。
|
||||
- 本地 Compose 仍只启动 Redis,不隐式增加 RocketMQ 生命周期。
|
||||
- 治理、MySQL 5.7、Schema 基线回归测试全部通过。
|
||||
|
||||
## 本机诊断
|
||||
|
||||
- `docker ps` 与本机进程检查 NameServer、Broker、Proxy,定位端口真实监听者。
|
||||
- `docker inspect rmqnamesrv` 核对镜像与端口映射。
|
||||
- `docker logs rmqnamesrv` 核对启动成功日志。
|
||||
- `nc` 检查 `9876`、`10911` 和 `8081` TCP 可达。
|
||||
- `mqadmin clusterList`、`topicList`、`brokerStatus` 检查 Broker 注册、Topic 路由与运行状态。
|
||||
|
||||
基础设施管理链路已验证。由于项目 Server 与 Node 客户端尚未实现,本版本不创建测试 Topic,也不执行项目消息生产和消费,并将此限制记录为未执行项。
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
## 1. 目标
|
||||
|
||||
本规范保证代码对普通开发者可连续阅读、对关键业务可解释、对历史版本可维护。规范适用于 Vue 3 前端、NestJS 后端、调度器、RabbitMQ Worker、数据适配器、规则引擎和 AI 分析模块。
|
||||
本规范保证代码对普通开发者可连续阅读、对关键业务可解释、对历史版本可维护。规范适用于 Vue 3 前端、NestJS 后端、调度器、RocketMQ Worker、数据适配器、规则引擎和 AI 分析模块。
|
||||
|
||||
## 2. 技术基线
|
||||
|
||||
- 前端:Vue 3、Vite、TypeScript、Dart Sass、Naive UI。
|
||||
- 后端:NestJS、TypeScript。
|
||||
- 数据库:MySQL 5.7.x,字符集 `utf8mb4`,排序规则 `utf8mb4_general_ci`;缓存:Redis;消息队列:RabbitMQ。
|
||||
- 数据库:MySQL 5.7.x,字符集 `utf8mb4`,排序规则 `utf8mb4_general_ci`;缓存:Redis;消息队列:RocketMQ 5.x。
|
||||
- 图表:Lightweight Charts负责K线和分时,ECharts负责热力图、分布和资金趋势。
|
||||
- AI:由服务端调用兼容 OpenAI 格式的付费 API,密钥不得下发浏览器。
|
||||
|
||||
@@ -51,7 +51,7 @@ Vue 页面可以包含与页面强绑定的小型展示逻辑;当子区域拥
|
||||
- 对外导出的公共接口、类型和关键函数。
|
||||
- 涨跌停、复权、停牌、午间休市等 A 股特殊规则。
|
||||
- 指标公式、阈值来源、单位、数据日期和缺失值处理。
|
||||
- RabbitMQ 的幂等、重试、死信和消息顺序假设。
|
||||
- RocketMQ 的 Topic、Tag、Group、幂等、重试、死信和消息顺序假设。
|
||||
- Redis 与 MySQL 一致性边界和缓存失效策略。
|
||||
- AI 输入裁剪、事实约束、降级和成本控制逻辑。
|
||||
- 看似可以简化但因兼容性或历史原因必须保留的实现。
|
||||
@@ -70,7 +70,9 @@ count += 1;
|
||||
|
||||
- 禁止无理由使用 `any`;外部输入先以 `unknown` 接收并校验。
|
||||
- HTTP API 使用版本化 OpenAPI 契约。
|
||||
- RabbitMQ 事件包含 `eventId`、`eventType`、`schemaVersion`、`occurredAt`、`tradeDate`、`traceId` 和 `idempotencyKey`。
|
||||
- RocketMQ 事件包含 `eventId`、`eventType`、`schemaVersion`、`occurredAt`、`tradeDate`、`traceId` 和 `idempotencyKey`。
|
||||
- Topic 使用稳定的业务域命名,环境隔离由部署配置的前缀完成;Tag 表达同一 Topic 内的事件类型,Consumer Group 表达独立消费进度,禁止把临时实例名作为 Group。RocketMQ 5.x Proxy Producer 不配置旧 Remoting Producer Group。
|
||||
- 需要顺序处理的消息必须明确消息组键,例如证券代码或交易日;未声明顺序键时不得依赖全局到达顺序。
|
||||
- 金额、成交额和比率必须明确单位,避免同一字段混用元、万元、亿元或百分比小数。
|
||||
- 数据来源、采集时间、交易日期、完整性和口径版本必须可追溯。
|
||||
|
||||
@@ -88,14 +90,14 @@ count += 1;
|
||||
- API、Scheduler、Worker 必须使用各自的配置 Schema,在进程启动时验证类型、格式、范围和条件必填项;配置错误立即退出。
|
||||
- 同一进程的开发与生产模板必须保持相同变量名。环境差异通过配置值、依赖注入和 Adapter 收敛,禁止在业务代码中散落 `APP_ENV` 分支。
|
||||
- 只有 `*.env.example` 可以提交;真实 `.env`、`*.env.local`、密码、Token 和 API Key 必须被 Git 忽略并由运行环境注入。
|
||||
- Web 只能使用公开的 `VITE_*` 变量。数据库、Redis、RabbitMQ、数据源和 AI 凭据禁止进入前端变量或构建产物。
|
||||
- MySQL、RabbitMQ、正式数据源与 AI 使用显式功能开关;关闭时连接变量可为空,开启后缺少任何必填值都必须拒绝启动。
|
||||
- Web 只能使用公开的 `VITE_*` 变量。数据库、Redis、RocketMQ、数据源和 AI 凭据禁止进入前端变量或构建产物。
|
||||
- MySQL、RocketMQ、正式数据源与 AI 使用显式功能开关;关闭时连接变量可为空,开启后缺少任何必填值都必须拒绝启动。
|
||||
- Docker Compose 与源码部署必须复用同一变量契约,禁止为某种部署方式建立语义不同的别名。
|
||||
- 生产配置必须位于发布目录之外,切换应用版本不得覆盖配置;日志和诊断输出必须对配置值脱敏。
|
||||
|
||||
## 9. 前端规范
|
||||
|
||||
- 页面不得直接访问第三方行情源、Redis、RabbitMQ 或 AI 服务。
|
||||
- 页面不得直接访问第三方行情源、Redis、RocketMQ 或 AI 服务。
|
||||
- 全局服务器状态使用 TanStack Vue Query,本地界面偏好使用 Pinia或轻量组合式函数。
|
||||
- Sass token集中管理颜色、间距、圆角、字号和断点。
|
||||
- A 股默认红涨绿跌,但状态必须同时提供文字或形状,不能只依赖颜色。
|
||||
@@ -105,8 +107,11 @@ count += 1;
|
||||
## 10. 后端与任务规范
|
||||
|
||||
- API、Scheduler和Worker作为独立进程维护,不在请求期间临时抓取全市场数据。
|
||||
- Scheduler只决定何时投递;RabbitMQ负责任务传输;Worker负责执行;MySQL负责事实记录;Redis负责当前快照和短期状态。
|
||||
- Scheduler 只决定何时投递;MessageBusAdapter 负责隔离客户端;RocketMQ 负责任务传输;Worker 负责执行;MySQL 负责事实记录;Redis 负责当前快照和短期状态。
|
||||
- 消费者必须幂等,消息确认只能发生在持久化或可验证处理完成后。
|
||||
- RocketMQ 可能重复投递;消费者不得把“收到一次”当作“只执行一次”,必须以 `idempotencyKey` 和业务唯一约束防重。
|
||||
- 普通重试使用 RocketMQ 消费重试;延迟任务使用受版本支持的定时/延迟消息;超过服务端 Consumer Group 最大投递次数后进入死信,必须可查询、告警和人工重放。
|
||||
- 业务代码只依赖项目定义的 `MessageBusAdapter` 和版本化事件契约,禁止直接依赖 RocketMQ SDK 类型;客户端、NameServer 或 Proxy 接入方式由基础设施适配层决定。
|
||||
- 免费数据源通过 Adapter 统一为内部模型,上层不得依赖供应商原始字段。
|
||||
|
||||
## 11. MySQL 5.7 兼容规范
|
||||
@@ -137,7 +142,7 @@ count += 1;
|
||||
- 功能和缺陷修复遵循测试先行:先看到测试因缺少行为而失败,再实现最小代码。
|
||||
- 纯规则和指标计算使用单元测试,期望值必须手工推导。
|
||||
- 数据源 Adapter 使用契约测试和固定样本。
|
||||
- HTTP 与 RabbitMQ 使用契约测试。
|
||||
- HTTP 与 RocketMQ 使用契约测试;消息测试必须覆盖 Topic、Tag、Group、序列化、重复投递、重试和死信边界。
|
||||
- 关键页面使用 Playwright流程测试和视觉截图对比。
|
||||
- 合并前必须通过类型检查、测试、构建和适用的视觉验证。
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
- [系统架构](architecture/system-architecture.md)
|
||||
- [ADR-0001:单仓库双项目独立部署](adr/ADR-0001-monorepo-independent-deploy.md)
|
||||
- [ADR-0002:GitNexus 双门禁](adr/ADR-0002-gitnexus-double-gate.md)
|
||||
- [ADR-0003:采用 RocketMQ 5.x 作为唯一消息队列](adr/ADR-0003-rocketmq-message-bus.md)
|
||||
|
||||
## 环境与部署
|
||||
|
||||
@@ -42,5 +43,6 @@
|
||||
- [GOV-005:MySQL 5.7 字符集与兼容性基线](features/GOV-005-mysql57-charset-baseline/manifest.yaml)
|
||||
- [GOV-006:开发、生产环境与双部署方式](features/GOV-006-environment-deployment-baseline/manifest.yaml)
|
||||
- [GOV-007:开发数据库 Schema 基线与版本门禁](features/GOV-007-development-schema-baseline/manifest.yaml)
|
||||
- [GOV-008:RocketMQ 消息队列架构调整](features/GOV-008-rocketmq-adoption/manifest.yaml)
|
||||
|
||||
功能档案是需求、设计、代码、测试、版本和回退之间的唯一正式关联入口。
|
||||
|
||||
@@ -4,7 +4,7 @@ import test from 'node:test';
|
||||
|
||||
const repoRoot = new URL('../../', import.meta.url);
|
||||
const processNames = ['api', 'scheduler', 'worker', 'web'];
|
||||
const sensitiveKeyPattern = /(PASSWORD|API_KEY|TOKEN|SECRET|RABBITMQ_URL)$/;
|
||||
const sensitiveKeyPattern = /(PASSWORD|API_KEY|TOKEN|SECRET)$/;
|
||||
|
||||
async function readRepoFile(relativePath) {
|
||||
return readFile(new URL(relativePath, repoRoot), 'utf8');
|
||||
@@ -53,7 +53,21 @@ test('模板不包含敏感值且 Web 只暴露 VITE 变量', async () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('生产模板禁止模拟数据并保持 MySQL 5.7 配置契约', async () => {
|
||||
test('生产模板禁止模拟数据并保持 MySQL 5.7 与 RocketMQ 配置契约', async () => {
|
||||
const rocketMqTemplates = new Map();
|
||||
for (const environment of ['development', 'production']) {
|
||||
for (const processName of ['scheduler', 'worker']) {
|
||||
rocketMqTemplates.set(
|
||||
`${environment}/${processName}`,
|
||||
parseEnvTemplate(
|
||||
await readRepoFile(`deploy/env/${environment}/${processName}.env.example`),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
const developmentScheduler = rocketMqTemplates.get('development/scheduler');
|
||||
const developmentWorker = rocketMqTemplates.get('development/worker');
|
||||
const productionScheduler = rocketMqTemplates.get('production/scheduler');
|
||||
const worker = parseEnvTemplate(await readRepoFile('deploy/env/production/worker.env.example'));
|
||||
|
||||
assert.equal(worker.get('APP_ENV'), 'production');
|
||||
@@ -61,7 +75,27 @@ test('生产模板禁止模拟数据并保持 MySQL 5.7 配置契约', async ()
|
||||
assert.equal(worker.get('MYSQL_ENABLED'), 'false');
|
||||
assert.equal(worker.get('MYSQL_CHARSET'), 'utf8mb4');
|
||||
assert.equal(worker.get('MYSQL_COLLATION'), 'utf8mb4_general_ci');
|
||||
assert.equal(worker.get('RABBITMQ_ENABLED'), 'false');
|
||||
assert.equal(worker.get('ROCKETMQ_ENABLED'), 'false');
|
||||
assert.equal(worker.get('ROCKETMQ_ENDPOINT'), '');
|
||||
assert.equal(worker.get('ROCKETMQ_TOPIC_PREFIX'), 'a-share-analysis');
|
||||
assert.equal(worker.get('ROCKETMQ_CONSUMER_GROUP'), 'a-share-analysis-worker');
|
||||
for (const [templateName, entries] of rocketMqTemplates) {
|
||||
assert.equal(
|
||||
[...entries.keys()].some((key) => key.startsWith('RABBITMQ_')),
|
||||
false,
|
||||
`${templateName} 禁止保留 RabbitMQ 变量`,
|
||||
);
|
||||
assert.equal(entries.has('ROCKETMQ_PRODUCER_GROUP'), false);
|
||||
assert.equal(entries.has('ROCKETMQ_MAX_RECONSUME_TIMES'), false);
|
||||
}
|
||||
for (const entries of [developmentScheduler, developmentWorker]) {
|
||||
assert.equal(entries.get('ROCKETMQ_NAMESRV_ADDR'), '127.0.0.1:9876');
|
||||
assert.equal(entries.get('ROCKETMQ_ENDPOINT'), '127.0.0.1:8081');
|
||||
}
|
||||
for (const entries of [productionScheduler, worker]) {
|
||||
assert.equal(entries.get('ROCKETMQ_NAMESRV_ADDR'), '');
|
||||
assert.equal(entries.get('ROCKETMQ_ENDPOINT'), '');
|
||||
}
|
||||
});
|
||||
|
||||
test('本地 Compose 仅启动 Redis 并提供健康检查', async () => {
|
||||
@@ -70,7 +104,22 @@ test('本地 Compose 仅启动 Redis 并提供健康检查', async () => {
|
||||
assert.match(compose, /services:\s*\n\s+redis:/);
|
||||
assert.match(compose, /healthcheck:/);
|
||||
assert.match(compose, /127\.0\.0\.1:/);
|
||||
assert.doesNotMatch(compose, /^\s{2}(mysql|rabbitmq|api|worker|scheduler|web):/m);
|
||||
assert.doesNotMatch(compose, /^\s{2}(mysql|rocketmq|api|worker|scheduler|web):/m);
|
||||
});
|
||||
|
||||
test('活动架构与部署文档只采用 RocketMQ 5.x', async () => {
|
||||
for (const relativePath of [
|
||||
'README.md',
|
||||
'docs/architecture/system-architecture.md',
|
||||
'docs/governance/code-development-standards.md',
|
||||
'docs/deployment/local-development.md',
|
||||
'docs/deployment/docker-compose-production.md',
|
||||
'docs/deployment/ubuntu-source-production.md',
|
||||
]) {
|
||||
const content = await readRepoFile(relativePath);
|
||||
assert.match(content, /RocketMQ 5\.x|RocketMQ/);
|
||||
assert.doesNotMatch(content, /RabbitMQ/);
|
||||
}
|
||||
});
|
||||
|
||||
test('生产源码部署使用独立 EnvironmentFile 并提供 Nginx 代理', async () => {
|
||||
|
||||
Reference in New Issue
Block a user