refactor: add shared logging crate

This commit is contained in:
2026-04-21 12:08:42 +08:00
parent 07fcbe4a2f
commit 854a7a2568
18 changed files with 280 additions and 68 deletions

View File

@@ -77,6 +77,8 @@
交付物:[../server-rs/crates/shared-contracts/README.md](../server-rs/crates/shared-contracts/README.md)
- [x] 创建 `crates/shared-kernel`
交付物:[../server-rs/crates/shared-kernel/README.md](../server-rs/crates/shared-kernel/README.md)
- [ ] 创建 `crates/shared-logging`
交付物:[../server-rs/crates/shared-logging/README.md](../server-rs/crates/shared-logging/README.md)
- [x] 创建 `crates/platform-auth`
交付物:[../server-rs/crates/platform-auth/README.md](../server-rs/crates/platform-auth/README.md)
- [x] 创建 `crates/platform-oss`
@@ -95,7 +97,7 @@
- [x] 接入统一配置加载
交付物:[../server-rs/crates/api-server/src/config.rs](../server-rs/crates/api-server/src/config.rs)
- [x] 接入统一日志与 tracing
交付物:[../server-rs/crates/api-server/src/logging.rs](../server-rs/crates/api-server/src/logging.rs)、[../server-rs/crates/api-server/src/app.rs](../server-rs/crates/api-server/src/app.rs)、[../server-rs/crates/api-server/src/main.rs](../server-rs/crates/api-server/src/main.rs)
交付物:[../docs/technical/RUST_SHARED_LOGGING_CRATE_DESIGN_2026-04-21.md](../docs/technical/RUST_SHARED_LOGGING_CRATE_DESIGN_2026-04-21.md)、[../server-rs/crates/shared-logging/src/lib.rs](../server-rs/crates/shared-logging/src/lib.rs)、[../server-rs/crates/api-server/src/app.rs](../server-rs/crates/api-server/src/app.rs)、[../server-rs/crates/api-server/src/main.rs](../server-rs/crates/api-server/src/main.rs)
- [x] 接入 `request_id` 中间件
交付物:[../server-rs/crates/api-server/src/request_context.rs](../server-rs/crates/api-server/src/request_context.rs)、[../server-rs/crates/api-server/src/app.rs](../server-rs/crates/api-server/src/app.rs)
- [x] 接入统一错误处理中间件

View File

@@ -4,6 +4,7 @@
## 文档列表
- [RUST_SHARED_LOGGING_CRATE_DESIGN_2026-04-21.md](./RUST_SHARED_LOGGING_CRATE_DESIGN_2026-04-21.md)Rust 工作区统一日志模块 `shared-logging` 的职责边界、API、输出风格与 `api-server` 迁移规则。
- [SPACETIMEDB_WECHAT_AUTH_STATE_TABLE_DESIGN_2026-04-21.md](./SPACETIMEDB_WECHAT_AUTH_STATE_TABLE_DESIGN_2026-04-21.md)`M2` 第七张微信 OAuth 状态表 `wechat_auth_state` 的字段、过期/消费语义、`wechat/start``wechat/callback` 的单次消费规则,以及多实例下的清理策略。
- [SPACETIMEDB_SMS_AUTH_EVENT_TABLE_DESIGN_2026-04-21.md](./SPACETIMEDB_SMS_AUTH_EVENT_TABLE_DESIGN_2026-04-21.md)`M2` 第六张短信鉴权统计表 `sms_auth_event` 的事件范围、统计口径、索引与和风控/审计表的协作边界。
- [SPACETIMEDB_AUTH_RISK_BLOCK_TABLE_DESIGN_2026-04-21.md](./SPACETIMEDB_AUTH_RISK_BLOCK_TABLE_DESIGN_2026-04-21.md)`M2` 第五张风控状态表 `auth_risk_block` 的作用域、活跃态、刷新/解除规则与读取派生约束。

View File

@@ -0,0 +1,155 @@
# Rust `shared-logging` crate 设计
日期:`2026-04-21`
## 1. 文档目的
这份文档用于明确 `server-rs/` 下统一日志模块的落地方式。
目标是把当前仅存在于 `crates/api-server/src/logging.rs` 的日志初始化逻辑,上提为一个可被多 crate 复用的独立 `shared-logging` crate并固定
1. 统一日志模块的职责边界
2. `api-server`、后续 `spacetime-module`、测试支撑与脚本入口的复用方式
3. 日志过滤、subscriber 初始化、输出风格的统一口径
4. 不允许继续把日志初始化散落到各主工程 crate 中
## 2. 当前基线
当前 Rust 工作区里的日志实现现状:
1. `api-server` 内部已有 `src/logging.rs`
2. 该文件负责创建 `EnvFilter` 并初始化 `tracing subscriber`
3. `main.rs` 直接调用 `init_tracing(&config)`
4. 其它 crate 尚未复用同一套日志初始化逻辑
当前问题:
1. 日志初始化逻辑被绑定在 `api-server` 内部,无法作为工作区级共享能力复用
2. 后续 `spacetime-module`、测试支撑、独立 worker、脚本入口若需要日志会继续复制粘贴
3. 当前没有独立 crate 作为“统一日志模块”承接输出风格、默认过滤器与 subscriber 初始化边界
## 3. crate 职责边界
### 3.1 `shared-logging` 负责
1. 提供工作区统一的 `tracing subscriber` 初始化入口
2. 提供统一的日志过滤器解析逻辑
3. 固定当前阶段的输出风格,例如 `compact``with_target(true)`
4.`api-server`、后续 `spacetime-module`、测试支撑与独立入口提供可复用初始化函数
### 3.2 它不负责
1. 保存业务日志事件结构体
2. 直接耦合 `Axum` 中间件或 `TraceLayer`
3. 处理业务 request id、response headers、error body
4. 承担供应商日志上报、链路追踪采样、远端日志聚合
### 3.3 与其他 crate 的边界
1. `shared-logging` 只提供“日志基础设施初始化”
2. `api-server` 继续负责 HTTP 访问日志的 `TraceLayer` 挂载
3. `request_context`、错误中间件、响应头模块继续负责 request id 与响应元信息串联
4. 若未来需要结构化埋点或审计事件,应进入对应业务 crate不进入 `shared-logging`
## 4. 目录与命名
统一落位:
1. `server-rs/crates/shared-logging`
当前阶段建议最小文件结构:
```text
server-rs/crates/shared-logging/
├─ Cargo.toml
├─ README.md
└─ src/
└─ lib.rs
```
说明:
1. 当前阶段只做库 crate不做独立二进制入口
2. `api-server``src/logging.rs` 迁出后,直接依赖 `shared-logging`
## 5. API 设计
当前阶段建议提供以下最小 API
1. `init_tracing(log_filter: &str) -> Result<(), io::Error>`
2. `resolve_env_filter(default_filter: &str) -> EnvFilter`
设计原因:
1. `api-server` 当前只需要一个初始化入口
2. 后续如 `spacetime-module` 需要不同默认过滤器,也可以复用 `resolve_env_filter(...)`
3. 避免在第一版就过度设计成复杂 builder
## 6. 配置约定
当前阶段仍保留现有配置来源:
1. `api-server` 默认读取 `GENARRATIVE_API_LOG`
2. 若环境变量未提供,则回落到配置对象中的 `log_filter`
3. `shared-logging` 不直接读取业务配置结构,只消费最终传入的默认 filter 字符串
这样做的原因:
1. 保持 `shared-logging` 对上层业务配置解耦
2. 避免把 `AppConfig` 类型反向沉到共享基础设施 crate
## 7. 输出风格约定
当前阶段固定沿用现有输出口径:
1. `compact`
2. `with_target(true)`
3. 基于 `EnvFilter` 做过滤
说明:
1. 先保证工作区统一
2. 后续若要引入 JSON 输出、环境区分或远端采集,再在 `shared-logging` 中集中演进
## 8. 落地规则
### 8.1 `api-server`
必须调整为:
1. 删除本地 `src/logging.rs`
2.`Cargo.toml` 中引用 `shared-logging`
3. `main.rs` 改为调用 `shared_logging::init_tracing(...)`
### 8.2 其它 crate
后续若需要日志初始化,统一按以下规则:
1. 优先依赖 `shared-logging`
2. 不再在各自 crate 内重复实现一份 `init_tracing`
## 9. 不允许的设计漂移
后续实现时禁止出现以下情况:
1. 再为 `api-server``spacetime-module` 各自复制一份 subscriber 初始化逻辑
2.`Axum``TraceLayer` 直接塞进 `shared-logging`
3. 把 request id、响应头、错误 envelope 这些 HTTP 语义放进 `shared-logging`
4. 为了抽象而把业务配置类型强耦合进共享日志 crate
## 10. 本任务完成定义
当以下条件满足时,统一日志模块任务视为完成:
1. `shared-logging` crate 已创建并加入 workspace
2. `api-server` 已改为依赖 `shared-logging`
3.`api-server/src/logging.rs` 已被移除
4. 工作区文档与任务清单已同步到“统一日志模块”口径
## 11. 依据文件
1. `server-rs/crates/api-server/src/logging.rs`
2. `server-rs/crates/api-server/src/main.rs`
3. `server-rs/crates/api-server/src/config.rs`
4. `server-rs/crates/api-server/README.md`
5. `backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md`

View File

@@ -258,6 +258,7 @@ server-rs/
│ ├─ module-ai/ # AI 编排模块 crate
│ ├─ shared-contracts/ # HTTP DTO / SSE event / 前后端兼容 contract
│ ├─ shared-kernel/ # 跨模块共享领域类型、ID、枚举、值对象
│ ├─ shared-logging/ # 工作区统一日志初始化与 tracing subscriber 基础设施
│ ├─ platform-auth/ # JWT、cookie、provider adapter
│ ├─ platform-oss/ # OSS 直传、签名、对象管理
│ ├─ platform-llm/ # DashScope / Ark / 其他模型适配
@@ -277,7 +278,8 @@ server-rs/
3. `crates/module-*` 保持与当前业务模块边界一一对应,已明确退出本轮的 `editor` 遗留模块除外;必要时可在 crate 内部再拆 `application``domain``spacetime` 子层次。
4. `crates/shared-contracts/` 负责与当前前端兼容的 JSON / SSE 协议。
5. `crates/shared-kernel/` 只放跨模块复用的数据结构和规则,不碰框架。
6. `crates/platform-*` 统一承接三方供应商与平台适配
6. `crates/shared-logging/` 负责统一日志初始化、过滤器解析与 subscriber 基础设施,不承接 HTTP 业务语义
7. `crates/platform-*` 统一承接三方供应商与平台适配。
命名补充说明:

9
server-rs/Cargo.lock generated
View File

@@ -25,12 +25,12 @@ dependencies = [
"http-body-util",
"serde",
"serde_json",
"shared-logging",
"time",
"tokio",
"tower",
"tower-http",
"tracing",
"tracing-subscriber",
"uuid",
]
@@ -572,6 +572,13 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "shared-logging"
version = "0.1.0"
dependencies = [
"tracing-subscriber",
]
[[package]]
name = "slab"
version = "0.4.12"

View File

@@ -5,6 +5,7 @@
resolver = "2"
members = [
"crates/api-server",
"crates/shared-logging",
]
[workspace.package]

View File

@@ -14,7 +14,7 @@
## 2. 当前阶段说明
当前目录已经完成以下三十项初始化:
当前目录已经完成以下三十项初始化:
1. 为新后端预留正式目录并把路径固定到仓库结构中。
2. 创建虚拟 workspace `Cargo.toml`,后续 crate 会逐项挂入。
@@ -35,21 +35,22 @@
17. 创建 `crates/module-ai/` 目录占位,固定 AI 编排模块 crate 落位。
18. 创建 `crates/shared-contracts/` 目录占位,固定前后端兼容 contract 共享 crate 落位。
19. 创建 `crates/shared-kernel/` 目录占位,固定跨模块共享领域内核 crate 落位。
20. 创建 `crates/platform-auth/` 目录占位,固定鉴权平台适配 crate 落位。
21. 创建 `crates/platform-oss/` 目录占位,固定 OSS 平台适配 crate 落位。
22. 创建 `crates/platform-llm/` 目录占位,固定大模型平台适配 crate 落位。
23. 创建 `crates/spacetime-client/` 目录占位,固定 SpacetimeDB 客户端适配 crate 落位。
24. 创建 `crates/tests-support/` 目录占位,固定测试支撑共享 crate 落位。
25. 创建 `scripts/dev.ps1`,固定 Windows 本地开发入口
26. 创建 `scripts/dev.sh`,固定 Unix-like 本地开发入口。
27. 创建 `scripts/test.ps1`,固定 Windows 本地测试入口。
28. 创建 `scripts/test.sh`,固定 Unix-like 本地测试入口。
29. 创建 `scripts/check.ps1`,固定 Windows 本地统一检查入口。
30. 创建 `scripts/check.sh`,固定 Unix-like 本地统一检查入口。
31. 创建 `scripts/smoke.ps1`,固定 Windows 本地冒烟验证入口。
32. 创建 `scripts/smoke.sh`,固定 Unix-like 本地冒烟验证入口。
33. 创建 `scripts/spacetime-dev.ps1`,固定 Windows 本地 SpacetimeDB 启动入口。
34. 创建 `scripts/spacetime-dev.sh`,固定 Unix-like 本地 SpacetimeDB 启动入口。
20. 创建 `crates/shared-logging/` 目录占位,固定工作区统一日志 crate 落位。
21. 创建 `crates/platform-auth/` 目录占位,固定鉴权平台适配 crate 落位。
22. 创建 `crates/platform-oss/` 目录占位,固定 OSS 平台适配 crate 落位。
23. 创建 `crates/platform-llm/` 目录占位,固定大模型平台适配 crate 落位。
24. 创建 `crates/spacetime-client/` 目录占位,固定 SpacetimeDB 客户端适配 crate 落位。
25. 创建 `crates/tests-support/` 目录占位,固定测试支撑共享 crate 落位
26. 创建 `scripts/dev.ps1`,固定 Windows 本地开发入口。
27. 创建 `scripts/dev.sh`,固定 Unix-like 本地开发入口。
28. 创建 `scripts/test.ps1`,固定 Windows 本地测试入口。
29. 创建 `scripts/test.sh`,固定 Unix-like 本地测试入口。
30. 创建 `scripts/check.ps1`,固定 Windows 本地统一检查入口。
31. 创建 `scripts/check.sh`,固定 Unix-like 本地统一检查入口。
32. 创建 `scripts/smoke.ps1`,固定 Windows 本地冒烟验证入口。
33. 创建 `scripts/smoke.sh`,固定 Unix-like 本地冒烟验证入口。
34. 创建 `scripts/spacetime-dev.ps1`,固定 Windows 本地 SpacetimeDB 启动入口。
35. 创建 `scripts/spacetime-dev.sh`,固定 Unix-like 本地 SpacetimeDB 启动入口。
后续任务会继续在本目录内按顺序补齐:

View File

@@ -8,11 +8,11 @@ license.workspace = true
axum = "0.8"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
shared-logging = { path = "../shared-logging" }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "net"] }
time = { version = "0.3", features = ["formatting"] }
tower-http = { version = "0.6", features = ["trace"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
uuid = { version = "1", features = ["v4"] }
[dev-dependencies]

View File

@@ -26,8 +26,8 @@
4. `src/app.rs`
5. `src/state.rs`
6. `src/config.rs`
7. `src/logging.rs`
8. 基础 `TraceLayer` 挂载与 `tracing subscriber` 初始化
7. 基础 `TraceLayer` 挂载
8. 接入 `shared-logging` 完成 `tracing subscriber` 初始化
后续与本 crate 直接相关的任务包括:
@@ -39,7 +39,7 @@
当前 tracing 约定:
1. 进程启动时统一初始化 `tracing subscriber`
1. 进程启动时通过 `shared-logging` 统一初始化 `tracing subscriber`
2. 默认日志过滤器来自 `GENARRATIVE_API_LOG`,未提供时回落到 `info,tower_http=info`
3. HTTP 访问日志统一通过 Axum 路由层的 `TraceLayer` 输出,后续 `request_id`、响应头与错误中间件继续在同一层扩展。

View File

@@ -1,19 +0,0 @@
use std::io;
use tracing_subscriber::{fmt, EnvFilter};
use crate::config::AppConfig;
// 统一在独立模块初始化 tracing避免入口层和后续测试入口重复散落 subscriber 配置。
pub fn init_tracing(config: &AppConfig) -> Result<(), io::Error> {
let env_filter = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new(config.log_filter.as_str()))
.unwrap_or_else(|_| EnvFilter::new("info"));
fmt()
.with_env_filter(env_filter)
.with_target(true)
.compact()
.try_init()
.map_err(|error| io::Error::other(format!("初始化 tracing subscriber 失败:{error}")))
}

View File

@@ -4,21 +4,21 @@ mod config;
mod error_middleware;
mod health;
mod http_error;
mod logging;
mod request_context;
mod response_headers;
mod state;
use shared_logging::init_tracing;
use tokio::net::TcpListener;
use tracing::info;
use crate::{app::build_router, config::AppConfig, logging::init_tracing, state::AppState};
use crate::{app::build_router, config::AppConfig, state::AppState};
#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
// 统一先从配置对象读取监听地址,避免后续把环境变量读取散落到入口和路由层。
let config = AppConfig::from_env();
init_tracing(&config)?;
init_tracing(&config.log_filter)?;
let bind_address = config.bind_socket_addr();
let listener = TcpListener::bind(bind_address).await?;

View File

@@ -1,22 +1,22 @@
# platform-auth 平台适配 package 占位说明
# platform-auth 平台适配 crate 占位说明
日期:`2026-04-20`
## 1. package 职责
## 1. crate 职责
`platform-auth` 是鉴权平台适配 package后续负责
`platform-auth` 是鉴权平台适配 crate后续负责
1. JWT 签发与校验适配
2. refresh cookie 读写与轮换适配
3. 手机验证码发送与校验适配
4. 微信 OAuth 相关平台适配
5.`module-auth``apps/api-server` 复用的鉴权基础设施能力
5.`module-auth``crates/api-server` 复用的鉴权基础设施能力
## 2. 当前阶段说明
当前提交仅完成目录占位,不提前进入 JWT、Cookie、短信与微信平台实现。
后续与本 package 直接相关的任务包括:
后续与本 crate 直接相关的任务包括:
1. 落地 JWT claims、签发与校验适配
2. 落地 refresh cookie 读取、写入与轮换适配
@@ -26,5 +26,5 @@
## 3. 边界约束
1. `platform-auth` 只承接平台适配,不承接 `module-auth` 的业务规则和状态真相。
2. 鉴权状态最终由 `module-auth``apps/spacetime-module` 管理,前端接口由 `apps/api-server` 暴露。
2. 鉴权状态最终由 `module-auth``crates/spacetime-module` 管理,前端接口由 `crates/api-server` 暴露。
3. 不允许把短信、微信、Cookie、JWT 等外部细节重新散落到多个业务模块中各自实现。

View File

@@ -1,10 +1,10 @@
# shared-contracts 共享 package 占位说明
# shared-contracts 共享 crate 占位说明
日期:`2026-04-20`
## 1. package 职责
## 1. crate 职责
`shared-contracts` 是前后端兼容 contract 共享 package后续负责
`shared-contracts` 是前后端兼容 contract 共享 crate后续负责
1. HTTP 请求与响应 DTO
2. SSE 事件结构与事件名约定
@@ -15,7 +15,7 @@
当前提交仅完成目录占位,不提前进入 DTO、事件与兼容结构实现。
后续与本 package 直接相关的任务包括:
后续与本 crate 直接相关的任务包括:
1. 对齐现有前端直接依赖的响应头与 envelope
2. 对齐 story、custom world、chat 等 SSE 事件结构
@@ -25,5 +25,5 @@
## 3. 边界约束
1. `shared-contracts` 只放协议类型与兼容结构,不承接业务规则、供应商适配或状态写入逻辑。
2. 各模块 package 对外暴露的协议优先复用这里的共享定义,避免重复散落。
3. 前端兼容契约一旦进入本 package就必须与任务清单和基线文档同步维护。
2. 各模块 crate 对外暴露的协议优先复用这里的共享定义,避免重复散落。
3. 前端兼容契约一旦进入本 crate就必须与任务清单和基线文档同步维护。

View File

@@ -1,10 +1,10 @@
# shared-kernel 共享 package 占位说明
# shared-kernel 共享 crate 占位说明
日期:`2026-04-20`
## 1. package 职责
## 1. crate 职责
`shared-kernel` 是跨模块共享领域内核 package后续负责
`shared-kernel` 是跨模块共享领域内核 crate后续负责
1. 共享 ID、值对象、枚举与基础领域类型
2. 共享时间、状态、版本、通用校验等基础规则
@@ -14,7 +14,7 @@
当前提交仅完成目录占位,不提前进入具体共享类型与基础规则实现。
后续与本 package 直接相关的任务包括:
后续与本 crate 直接相关的任务包括:
1. 统一用户、会话、世界、角色、资产等核心 ID 类型
2. 统一时间戳、版本号、状态枚举等共享结构
@@ -24,5 +24,5 @@
## 3. 边界约束
1. `shared-kernel` 只放跨模块最小共享内核,不承接具体业务模块的私有规则。
2. 任何进入本 package 的类型都必须证明至少被多个模块稳定复用。
2. 任何进入本 crate 的类型都必须证明至少被多个模块稳定复用。
3. 不能把主模块实现重新堆进共享内核,避免形成新的“大公共垃圾桶”。

View File

@@ -0,0 +1,8 @@
[package]
name = "shared-logging"
edition.workspace = true
version.workspace = true
license.workspace = true
[dependencies]
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }

View File

@@ -0,0 +1,32 @@
# shared-logging 共享日志 crate 占位说明
日期:`2026-04-21`
## 1. crate 职责
`shared-logging` 是 Rust 工作区统一日志基础设施 crate后续负责
1. 统一 `tracing subscriber` 初始化入口
2. 统一日志过滤器解析逻辑
3. 统一当前阶段日志输出风格
4.`api-server`、后续 `spacetime-module`、测试支撑与独立入口提供可复用日志初始化能力
## 2. 当前阶段说明
当前阶段已完成最小落地:
1. 提供 `resolve_env_filter(...)`
2. 提供 `init_tracing(...)`
3.`api-server` 的日志初始化逻辑迁出为共享 crate
后续与本 crate 直接相关的任务包括:
1. 根据环境扩展日志输出格式
2. 补充测试入口、worker 入口与其它主工程 crate 的统一接入
3. 视需要补充 JSON 输出、链路追踪或远端采集适配
## 3. 边界约束
1. `shared-logging` 只承接日志初始化与基础设施,不承接 HTTP 业务语义。
2. `TraceLayer`、request id、响应头、错误 envelope 等 HTTP 逻辑继续留在 `api-server`
3. 不允许把业务埋点、审计事件或供应商日志适配塞进本 crate。

View File

@@ -0,0 +1,22 @@
use std::io;
use tracing_subscriber::{fmt, EnvFilter};
// 统一解析工作区日志过滤器,优先环境变量,其次回落到调用方传入的默认值。
pub fn resolve_env_filter(default_filter: &str) -> EnvFilter {
EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new(default_filter))
.unwrap_or_else(|_| EnvFilter::new("info"))
}
// 统一初始化 tracing subscriber避免各入口重复散落相同配置。
pub fn init_tracing(default_filter: &str) -> Result<(), io::Error> {
let env_filter = resolve_env_filter(default_filter);
fmt()
.with_env_filter(env_filter)
.with_target(true)
.compact()
.try_init()
.map_err(|error| io::Error::other(format!("初始化 tracing subscriber 失败:{error}")))
}

View File

@@ -1,20 +1,20 @@
# tests-support 共享 package 占位说明
# tests-support 共享 crate 占位说明
日期:`2026-04-20`
## 1. package 职责
## 1. crate 职责
`tests-support` 是测试支撑共享 package后续负责
`tests-support` 是测试支撑共享 crate后续负责
1. contract、integration、smoke 测试的共享夹具与辅助工具
2. 测试环境配置、测试数据装配与断言工具
3.`apps/api-server``apps/spacetime-module` 与各模块 package 复用的测试基础设施能力
3.`crates/api-server``crates/spacetime-module` 与各模块 crate 复用的测试基础设施能力
## 2. 当前阶段说明
当前提交仅完成目录占位,不提前进入测试夹具、断言工具与 smoke 支撑实现。
后续与本 package 直接相关的任务包括:
后续与本 crate 直接相关的任务包括:
1. 设计接口测试与 contract 回归共享夹具
2. 设计 reducer / view / projection 测试辅助
@@ -25,4 +25,4 @@
1. `tests-support` 只承接测试支撑能力,不承接业务规则实现。
2. 测试夹具要尽量贴近真实 contract 与真实模块边界,避免重新引入脱离现网的伪环境。
3. 不允许把测试辅助逻辑散落到各模块 package 中重复实现。
3. 不允许把测试辅助逻辑散落到各模块 crate 中重复实现。