answer from Qwen
这是一个典型的并发提交与审批顺序一致性问题。核心诉求是:
当业务A的“类型1”多次提交到业务B的“类型1”进行审核时,即使多次提交并发发生,最终审核通过的结果必须反映最新的提交内容,且审批流程应按提交顺序执行(或至少结果体现最新状态)。
一、问题本质分析
- 多次提交:业务A类型1可多次提交,每次生成一条待审记录(提交版本)。
- 审批流程:业务B类型1对每条提交记录进行审核。
- 目标:
- 顺序性:先提交的应先审核(可选,但有助于逻辑清晰)。
- 最终一致性:无论中间过程如何,最终审核通过的结果必须是最后一次提交的内容。
- 避免过期审批:不能让旧提交在新提交之后被批准并覆盖新状态。
二、解决方案设计
✅ 核心思路:版本控制 + 状态锁 + 审批有效性校验
1. 引入“提交版本号”或“时间戳”字段
每次业务A类型1提交时,系统自动生成一个递增的版本号(或使用高精度时间戳):
{
"submit_id": "S123",
"biz_a_type": "type1",
"biz_b_type": "type1",
"content": "...",
"version": 3, // 递增整数,或使用UUID+时间戳组合
"submit_time": "2025-10-20T10:00:00Z",
"status": "pending"
}
建议使用单调递增整数版本号(如数据库自增ID或业务级版本计数器),比时间戳更可靠(避免时钟漂移)。
2. 业务B审核时,强制校验“是否为最新提交”
在审批操作(通过/拒绝)时,执行以下逻辑:
def approve_submission(submit_id):
submission = get_submission(submit_id)
latest = get_latest_pending_or_approved_submission_for(biz_a_type="type1", biz_b_type="type1")
if submission.version < latest.version:
raise Exception("该提交已过期,存在更新的提交,请审核最新版本。")
# 正常执行审批逻辑
mark_as_approved(submission)
这样即使旧提交还在审批队列中,一旦有新提交,旧提交就无法被批准(或自动作废)。
3. 自动作废旧提交(推荐)
当业务A类型1再次提交时,系统自动将该业务对(A类型1 → B类型1)下所有未完成(pending)的旧提交标记为“已废弃”:
def submit_from_a_to_b(content):
# 1. 查询当前未完成的提交
pending_subs = query_pending_submissions(
biz_a_type="type1",
biz_b_type="type1"
)
# 2. 标记为废弃
for sub in pending_subs:
sub.status = "abandoned"
save(sub)
# 3. 创建新提交
new_version = get_next_version("type1->type1")
new_sub = create_submission(
content=content,
version=new_version,
status="pending"
)
return new_sub
✅ 优点:审批人员只看到最新提交,避免混淆;系统逻辑清晰。
4. 审批界面优化(用户体验)
- 在业务B的审批列表中,只展示每个业务对的最新提交(或明确标注“此为旧版本,已被新提交替代”)。
- 若审批人试图审批旧版本,前端/后端提示:“该申请已被更新,请审批最新版本”。
三、可选增强:审批队列顺序控制
如果业务要求严格按提交顺序审批(即使有新提交,也要先审完旧的),则需引入审批队列 + 状态锁:
- 使用一个FIFO队列管理待审任务。
- 每次提交入队,审批时从队首取。
- 但审批通过前,检查是否为最新版本(同上)。
- 若不是最新,则跳过(或自动拒绝),继续处理下一个。
⚠️ 注意:这种模式可能导致审批积压,且最终结果仍需以最新提交为准,因此**“自动废弃旧提交”通常是更优解**。
四、数据库设计建议
CREATE TABLE submission (
id BIGINT PRIMARY KEY,
biz_a_type VARCHAR(50) NOT NULL,
biz_b_type VARCHAR(50) NOT NULL,
content JSON,
version INT NOT NULL, -- 业务对内的递增版本
status ENUM('pending', 'approved', 'rejected', 'abandoned') DEFAULT 'pending',
submit_time DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_biz_pair_status (biz_a_type, biz_b_type, status),
INDEX idx_version (biz_a_type, biz_b_type, version DESC)
);
查询最新提交:
SELECT * FROM submission
WHERE biz_a_type = 'type1'
AND biz_b_type = 'type1'
AND status IN ('pending', 'approved')
ORDER BY version DESC
LIMIT 1;
五、总结:推荐方案
| 目标 |
实现方式 |
| 保证最终结果为最新提交 |
每次新提交时,自动废弃旧的 pending 提交 |
| 防止旧提交被误审 |
审批时校验版本号,非最新则拒绝 |
| 简化审批流程 |
审批列表只展示最新 pending 提交 |
| 可追溯历史 |
保留所有提交记录(含 abandoned),供审计 |
✅ 最终效果:无论业务A提交多少次,业务B只会审批最新的一次,且审批通过后系统状态即为最新提交内容,满足业务一致性要求。
如需进一步结合具体技术栈(如 Kafka、Redis、工作流引擎等),可继续补充场景细节。
change of mine
处理不同状态的数据
