LabHub
学习 学习路径 课程

FDE综合实战:仓库收到了三次相同订单

仓库收到了三次相同订单

在 LabHub 中继续学习

目标

实现一个 Python CLI,用于验证客户的合成订单 CSV,并在虚拟仓库中创建预留。 即使重复运行同一文件或响应丢失,也不得重复创建预留,并应交接未解决项目。

为什么重要

API 调用成功与客户业务完成不是一回事。未收到响应时一律重发,可能会再次创建已经保存的订单。 反之,如果完全禁止重试,又会丢失在保存前失败的正常订单。本练习同时处理输入契约、幂等键、持久化账本和重试上限。 这是一个没有真实出库、支付或客户信息的虚拟机器人零件仓库。不得直接读取或修改对方账本文件,只能通过 HTTP 契约集成。

预计耗时 80 分钟。请在默认 60 分钟会话结束前使用“+时间”延长(最长 180 分钟)。 会话结束后,/root/handoff 中的文件会消失。请在结束前将所需代码另存到个人工作区。

材料与执行契约

先阅读简报和执行契约。输入最大为 256KiB、100 行,数量为 1~5 个字符。 只将未被搁置的订单按 API 正文 order_id、sku、quantity 准备。邮件地址不得包含在传输、日志或报告中。 向评估器传递程序路径,以及 plan/send/chaos/repeat/drift/outage 中的检查名称。 示例:python3 /opt/lab/handoff/evaluate.py /root/handoff/sync.py plan 评估器会创建隔离的临时数据和服务器并自行关闭,因此无需提前启动单独服务器。 评估数据会更改部分订单号、SKU 和数量。不要硬编码所提供 CSV 的结果。

步骤

  1. 创建 /root/handoff,并将起始代码复制为 sync.py。在 scope.json 中记录业务 warehouse-reservation、业务键 order_id、send_pii=false、max_attempts=4、retryable_statuses=[503]、conflict_policy=hold_order、approval=review_only。JSON 的键名为 workflow、business_key、send_pii、max_attempts、retryable_statuses、conflict_policy、approval。
  2. 在 sync.py 中实现完整 CSV 验证和计划报告。默认模式发送 0 次 HTTP 请求,outcomes 为空数组。同一订单中出现无效行或冲突时,整个订单都应搁置;内容相同的行只将第一行列为候选,其余归入 duplicates。使用 plan 检查确认。
  3. 实现 sync.py 的 --send 分支。在正常服务器上只 POST 候选订单,并通过 GET /orders/<订单编号> 确认恰好有一个预留,且其内容与 ID 正确。报告的七个字段、outcomes 的四个字段以及退出码 0/2 均遵循执行契约。使用 send 检查与实际账本核对。
  4. 在 sync.py 中实现每次请求 1 秒超时、保持相同订单键,对 503 和连接错误最多尝试四次且间隔 0.1 秒。通过 chaos 检查,处理保存前返回 503 和保存后响应丢失两种情况。4xx 不得重试。
  5. 确认 sync.py 在下一次执行中仍使用相同业务键。repeat 检查会使用同一账本重启服务器,并再次执行相同输入。如果新增预留数量增加或 ID 变化,请修正每次执行都会变化的键以及重试分支。
  6. 实现 sync.py,确保已预留订单的数量发生变化时,不会通过新键绕过冲突。drift 检查会在第二次执行中更改部分数量。遇到 409 时,只进行一次 POST 就停止,结果保留为 rejected 和 null,并维持现有预留。
  7. 确认持续返回 503 时,sync.py 会在每个订单完成四次 POST 后停止,并记录 unconfirmed 和 null。运行 outage 检查。无法通过查询确认的结果也不得标记为成功。
  8. 使用当前实现运行全部六项检查,生成 handoff.json。使用评估器的 receipt 模式,记录实现与样本哈希、案例列表、review_only 决定、未解决的无效数量与冲突订单,以及实验限制。最终评分会同时读取 scope.json、sync.py 和 handoff.json,并重新验证执行情况。

参考

从客户描述中固定工作范围

请区分业务键和传输事件。发生冲突时,不要由工程师选择数量,而应搁置整个订单。

发送前对七行数据分类

使用 csv.DictReader 读取整个文件,按 order_id 分组后分类。CSV 解析器的默认字段限制也应与输入上限一致。如果发送前 7 行后才发现第 8 行存在冲突,就已经太晚了。

通过查询确认正常预留

对比 POST 响应与 GET 账本中的 ID、SKU 和数量。发送结果中仍有搁置项时,使用退出码 2 表示。

恢复保存前失败与响应丢失

始终使用相同的 order_id 作为幂等键。错误类型、尝试次数和业务确认状态彼此独立。

由下一位负责人重新运行同一文件

检查键中是否混入当前时间或本次执行的 UUID。不仅现有预留数量必须相同,ID 也必须相同。

不要将变化后的数量伪装成新订单

若将正文哈希用作键,数量变化时会创建新预留。遇到 409 时,不要重试或替换键,而应将其保留为拒绝结果。

仓库持续故障时停止

即使达到最大尝试次数,也不要改为成功状态。未经确认的预留 ID 应为 null。

交接执行依据与未解决项目

使用 receipt 模式重新验证当前代码。修改代码后,不要只修改哈希,而应重新执行验证。