Files
SMANAGE/GVSDSDK_IssueReport.md

144 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GVSDSDK 问题报告
> 基于 `gvsdsdk` 包源码审查(2026-08-10),结合本会话代码阅读与项目既有文档(SAAS_ARCHITECTURE.md、项目记忆)。
> 范围:`d:\SMANAGE\gvsdsdk`(约 15k 行 Python,55 个文件)。
> 说明:问题按严重度分级,标注可定位位置与修复建议;部分问题为设计取舍,标注"既定决策"。
---
## 1. 问题总览
| # | 等级 | 分类 | 问题 |
|---|---|---|---|
| 1 | 高 | 事务 | `_call_service` 响应非 JSON 时事务卡死(Running 悬挂) |
| 2 | 高 | 事务 | 补偿失败后无重试补偿入口,事务只能人工兜底 |
| 3 | 高 | 架构 | 非托管模型与主库 schema 同步靠人工,migrations 冻结后漂移风险 |
| 4 | 中 | 架构 | User/Dept/Workgroup/Shop 无 TenantUUID,跨租户查询需 JOIN |
| 5 | 中 | 事务 | MaxRetries 无自动重试;RetryStep 无行锁 |
| 6 | 中 | 事务 | 无步骤间数据流(StepResult 不注入后续步骤) |
| 7 | 中 | 事务 | 超时以 CreateTime 起算,非空闲超时 |
| 8 | 中 | 权限 | ABAC 名实不符(本质是 RBAC 字符串集合) |
| 9 | 中 | 架构 | CompanyUUID 全链路冗余无 DB 约束,一致性靠应用层 |
| 10 | 中 | 工程 | 核心链路(Saga/分佣/支付/鉴权)零自动化测试 |
| 11 | 低 | 架构 | UserRole 遗留废弃字段 DeptUUID/WorkgroupUUID 仍在 schema |
| 12 | 低 | 事务 | TransactionResult 恒为空 |
| 13 | 低 | 事务 | 无幂等键,重复执行副作用靠业务自觉 |
| 14 | 低 | 工程 | 惰性加载 130+ 符号 → 无静态类型、IDE 跳转弱 |
| 15 | 低 | 工程 | 类型注解缺失(auth/managers.py 自认暂缓) |
| 16 | 低 | 文档 | SAAS_ARCHITECTURE.md 技术债描述与实际现状漂移 |
---
## 2. 详细问题
### 2.1 高风险
#### #1 响应非 JSON 时事务卡死(Saga)
- **位置**:`gvsdsdk/msync/transaction.py` → `gvsds/apps/msync/transaction.py` `_call_service`(L538-566)
- **问题**:`resp.json()` 解析失败抛 JSONDecodeError,未被任何异常分支捕获;Execute 循环中断,事务永久停在 `Running`,不触发补偿,只能等 300s 超时兜底。
- **建议**:捕获 `(ValueError, requests.RequestException)` 统一转 `StepExecutionError`,确保失败必进补偿链路。
#### #2 补偿失败无法重试补偿(Saga)
- **位置**:`gvsds/apps/msync/transaction.py` `Compensate`(L256-314)
- **问题**:补偿异常时步骤状态停留在 `Compensating`(非 Completed),再次 Compensate 的 completed_steps 查询不到该步骤 → 永远补不回来,事务 FAILED 待人工;无 re-compensate 接口。
- **建议**:补偿失败步骤状态改 `Failed`,新增 `RetryCompensate` 入口(复用 RetryStep 骨架 + `select_for_update`)。
#### #3 非托管模型与主库 schema 同步靠人工
- **位置**:`gvsdsdk/models.py`(全部模型 `managed=False`)
- **问题**:SDK 只映射不迁移,主库表结构由 gvsds 侧维护;migrations 冻结后(gvsdsdk/migrations 仅 1 个 `0001_drop_userdept`),字段新增/改名需人工双端同步,漏改一端即运行时静默漂移。
- **证据**:gvsds 侧已无 `class Role/Permission/UserRole` 定义(gerp/models.py L778 从 gvsdsdk import,双份模型实际已收敛),收敛后 SDK 成为唯一模型源,但其结构约束力仅靠约定。
- **建议**:建立 SDK 模型 ↔ 主库 schema 的一致性校验(如启动时 `_check_schema` 对照 db_table 字段清单),或恢复按 SDK 生成迁移。
### 2.2 中风险
#### #4 部分表无 TenantUUID
- **位置**:`gvsdsdk/models.py` User(L186)/ Department(L500)/ Workgroup(L1302)/ Shop(L831)
- **问题**:跨租户查询需经 Company→Tenant JOIN;租户删除/隔离审计困难(SAAS_ARCHITECTURE.md 6.2 已列)。
- **建议**:向租户语义表补 `TenantUUID` 列并回填存量(迁移脚本),简化 `EnsureDefaultRoleForUser` 等处的租户解析链。
#### #5 MaxRetries 无自动重试;RetryStep 无行锁
- **位置**:`gvsds/apps/msync/transaction.py` Execute(L211-244)/ RetryStep(L316-359)
- **问题**:正向流程失败直接补偿,`MaxRetries`/`CanRetry` 仅约束手动重试;RetryStep 无 `select_for_update`,并发重试竞态。
- **建议**:Execute 内按 `CanRetry` 内联重试(可配置开关);RetryStep 加行锁。
#### #6 无步骤间数据流
- **位置**:`gvsds/apps/msync/transaction.py`
- **问题**:`StepResult` 不注入后续步骤 payload;`TransactionPayload` 创建后不参与执行链。真实 Saga 的"A 输出 → B 输入"场景只能创建时预置全部数据。
- **建议**:执行时将上一步 StepResult 合并进下一步 ActionPayload(向后兼容可选)。
#### #7 超时以 CreateTime 起算
- **位置**:`gvsds/apps/msync/models.py` `IsTimedOut`(L232-239)
- **问题**:事务总预算 = 创建后 300s,非"最近活动空闲超时";多步骤慢事务易误伤,无活动推进重置机制。
- **建议**:改为基于 `UpdateTime` 空闲判定,或事务级 heartbeat 推进。
#### #8 ABAC 名实不符
- **位置**:`gvsdsdk/models.py` UserABAC(L798-810);`gvsdsdk/auth/permissions.py`
- **问题**:`HierarchicalPermissionIdentifiers` 为逗号分隔字符串集合,本质是简化 RBAC,无属性(时间/IP/资源所有者/字段级)判定能力;对外宣称 ABAC,扩展受限。
- **建议**:短期文档更正为"属性标识符补充层";中期按策略表重构为真 ABAC。
#### #9 CompanyUUID 冗余无 DB 约束
- **位置**:`gvsdsdk/models.py` UserRole/RolePermission/UserRoleDepartment/UserRoleWorkgroup/RoleShop
- **问题**:冗余隔离列无数据库级一致性约束,删公司/改归属时应用层漏写即脏数据;且各表隔离语义靠"约定一致"。
- **建议**:至少对高频路径(UserRole/UserRoleDepartment)加索引与清理任务;长期考虑外键约束。
#### #10 核心链路零自动化测试
- **位置**:`gvsdsdk` 无 tests 目录;`gvsds/tests` 仅 test_ip_filter/test_money/test_storage 三文件
- **问题**:Saga 编排/补偿、分佣计算、支付网关、鉴权链路均无回归保障;本报告 #1/#2 类缺陷正是无测试的产物。
- **建议**:优先补:Saga 状态机转换、补偿幂等、RoleManager 鉴权链路、金额计算四组单测。
### 2.3 低风险
#### #11 UserRole 遗留废弃字段
- **位置**:`gvsdsdk/models.py` UserRole(L759-760)
- **问题**:DeptUUID/WorkgroupUUID 已废弃(注释禁止写入),但 schema 仍在,易被旧代码误写,语义歧义残留。
- **建议**:迁移清理列,或至少全库扫描确认零写入后移除。
#### #12 TransactionResult 恒为空
- **位置**:`gvsds/apps/msync/transaction.py`
- **问题**:模型字段存在,Execute/Compensate 从不写入,`GetDetail().Result` 恒 null。
- **建议**:终态统一写入步骤汇总。
#### #13 无幂等键
- **位置**:`gvsds/apps/msync/transaction.py` `_call_service`
- **问题**:无 Idempotency-Key;崩溃窗口内重复执行 action 的副作用靠业务补偿函数兜底。
- **建议**:HTTP 头携带事务码+步骤号幂等键,工作服务侧去重(可选)。
#### #14 惰性加载无静态类型
- **位置**:`gvsdsdk/__init__.py`(PEP 562 `__getattr__`,130+ 符号)
- **问题**:动态属性解析:IDE 跳转/补全弱、运行时属性访问有开销、`__all__` 未精确导出。
- **建议**:保留惰性加载同时补充 `.pyi` 类型桩或精确 `__all__`。
#### #15 类型注解缺失
- **位置**:`gvsdsdk/auth/managers.py`(L12 注释自认"类型注解暂缓")
- **问题**:~14k 行 Python 大面积无注解,与"双类导出"(自有实现/服务端转发)叠加后调用侧无类型保障。
- **建议**:对公开 Manager 方法渐进补注解,优先 RoleManager/OrderManager。
#### #16 架构文档漂移
- **位置**:`SAAS_ARCHITECTURE.md` 6.2 节
- **问题**:仍记录"Role/Permission 模型双份定义未收敛",实际 gvsds 侧已改为 `from gvsdsdk.models import`(gerp/models.py L778),双份已收敛;文档未同步。
- **建议**:更新技术债表,标注已收敛项,避免误导后续维护。
---
## 3. 优先级建议
| 优先级 | 动作 | 对应问题 |
|---|---|---|
| P0 | `_call_service` 异常兜底,失败必进补偿 | #1 |
| P0 | 补偿失败可重试(RetryCompensate + 行锁) | #2 |
| P1 | SDK 模型 ↔ 主库 schema 一致性校验 | #3 |
| P1 | Saga/鉴权/分佣/支付核心链路补单测 | #10 |
| P2 | 自动重试、步骤数据流、空闲超时、TransactionResult 写入 | #5/#6/#7/#12 |
| P2 | 补 TenantUUID、清理 UserRole 遗留列 | #4/#11 |
| P3 | 文档更正 ABAC 定位、更新架构文档、补类型桩 | #8/#14/#15/#16 |
---
## 4. 结论
GVSDSDK 已从"薄封装"演进为通用 SAAS 服务层(P0/P1/P2 服务层化迁移完成),架构方向正确、收敛彻底;当前主要风险集中在**事务可靠性与工程保障**:2 项高风险缺陷(#1/#2)会直接造成线上事务悬挂或补偿不完整,建议优先修复;其次为模型层 schema 同步靠人工(#3)与核心链路零测试(#10)带来的长期回归风险。
---
*报告人:TraeCode(2026-08-10)*