easynet.run · 全部问题场景

重试之前,先查清订单到底有没有创建

采购助手提交补货单后显示超时,采购员点了重试。过一会儿,两张相同订单都出现在供应商后台。第一次失败的可能只是回复,不是创建动作;屏幕上的等待结束,并没有替业务决定订单是否存在。

订单平台已有幂等键和状态查询时,应先使用它们。只有一个服务的场景,用事务和唯一约束更直接。EasyNet 不提供一个能替代这些保证的回执;它的作用是多个助手经过同一操作入口时,保留可追踪的尝试与调用身份。

适配器需要提供两个明确动作:提交这次购买意图,以及查询这次购买意图的结果。提交输入包含业务认可的稳定请求键、商品和数量;重试仍用同一业务键。调用记录的标识可以关联业务键,但两者不是天然等价,更不能每次重试都新建一笔意图。

查询返回应区分处理中、已创建、明确未创建和暂时无法确认。得到订单号后,助手展示的是原系统记录;查不到而又无法排除已提交时,进入待核对,不擅自创建第二单。业务键相同而数量变化,也必须让适配器拒绝或要求重新确认。

上游订单凭据留在提供方,调用者的权限只覆盖自己的采购范围。谁能下单、谁能查询,仍由业务适配器和授权共同检查。取消、退款是另一个有副作用的操作,不能因为原请求超时就自动执行补偿。

验证时刻意让订单已经落库、回复却丢失,再让同一采购范围内获准的第二个调用者查询原业务请求。确认只有一张订单,也确认不同参数不能被同一个键悄悄接受。业务幂等、查询和对账尚需按订单系统实现;这个方案要消除的是“未知就再做一次”,不是宣称网络调用永远只执行一次。

  1. 01

    提交补货意图

    固定业务键和数量

  2. 02

    回复丢失

    显示未知,不宣告失败

  3. 03

    查询原订单

    同一业务键取回原订单号

丢失回复后查原请求,不产生第二个购买意图。

同一键的参数必须一致

进程内示例只演示参数冲突检查;生产需持久事务与上游认可的幂等实现,不是网络一次执行保证。

本地示例 · python
orders = {}
def submit(key, item, quantity):
    intent = (item, quantity)
    if key in orders:
        if orders[key]["intent"] != intent:
            raise ValueError("request key reused with different input")
        return orders[key]["order_id"]
    orders[key] = {"intent": intent, "order_id": "order-001"}
    return "order-001"

submit("restock-2026-09-A", "paper", 10)  # reply lost
assert submit("restock-2026-09-A", "paper", 10) == "order-001"
assert len(orders) == 1
try:
    submit("restock-2026-09-A", "paper", 20)
except ValueError as error:
    print(error)

预期结果:保留一条记录;改成 20 件时输出参数冲突,不能悄悄接受。

接入时的检查项
  • 模拟服务已提交但客户端未收到回复,是否仍只生成一笔业务记录。
  • 相同业务键携带不同参数时是否明确拒绝。
  • 未知状态是否不会被显示为已取消或已退款。
源码与接入资料