SWE / Backend · Virtual Onsite AI Code Craft

DoorDash 退款 DAG Workflow:部分退款、重试与用户等待

DoorDash AI Code Craft 可追溯设计题:订单超时退款工作流的 DAG 执行、完整/部分退款、重复 API 调用、失败恢复和慢路径优化。

题目重点:DoorDash AI Code Craft 可追溯设计题:订单超时退款工作流的 DAG 执行、完整/部分退款、重复 API 调用、失败恢复和慢路径优化。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 可见题目没有公开 DAG 节点、边、已有代码接口或外部退款 API。以下是训练设计,不能当成现场 starter 的逐字重建,也不提供声称可运行原题的代码。
  • 订单超时事件触发一笔 refund_request。总可退款余额 = 已成功收款 − 已成功/待确认退款;部分退款金额由产品政策与服务端校验,币种和整数最小单位与原支付一致。
  • 外部退款 API 可能超时且结果未知;同一 refund_request 使用稳定 provider idempotency key。用户请求可以先返回 accepted + refund_id,后续查询状态。

解题路线

  1. 把 DAG 定义为有类型节点与依赖:ValidateOrder → DetermineEligibility → CalculateAmount → FraudReview/PolicyCheck → CreateRefundAttempt → CallProvider → Reconcile → Notify。可并行的独立读节点并行,但写款节点只在所有前置检查完成后执行。
  2. 引擎持久化 workflow_id、definition_version、每节点输入摘要、状态、attempt、输出引用和错误。只有所有父节点 SUCCESS 才将子节点 READY;worker 以 lease claim 节点,用唯一键写结果和 outbox,故障后从已完成节点继续,而非重跑整图。
  3. 全额/部分退款共用同一金额校验链,部分退款须检查累计已退+待处理不超过可退款额;对同一订单的并发退款在数据库事务内锁定或使用条件更新,防超退。欺诈/人工审核节点可挂起工作流,不阻塞 worker。
  4. 外部调用超时进入 UNKNOWN,先按 provider attempt ID 查询,再决定同 key 重试;不能换新 key 盲发第二笔。回调与主动查询都走同一状态机,并按 provider event_id 去重。

手动走一遍

用户订单已收 40 美元,因部分商品缺失批准退 12 美元。工作流先校验订单与累计退款余额,再记录 12 美元 attempt;Provider 接收后响应超时,节点标 UNKNOWN。用户立即看到 refund_id 与处理中;异步查询确认成功,再写退款 ledger、通知用户。若用户重复提交同一 request_id,返回同一 workflow;若另提 35 美元,则因 12+35>40 被拒。金额只用于训练示例。

规模与取舍

DAG 有 V 个节点、E 条依赖,校验/拓扑准备 O(V+E),状态存储 O(V+E) 每个工作流。端到端延迟主要是最慢依赖链上的节点耗时之和,而非所有节点总和;并行化独立读、缩短同步链和异步返回可减小用户等待,但资金最终状态仍由 provider 确认。

易错点与追问

容易失分的边界

  • 把整条工作流写成一个同步 HTTP 请求,任何审核或 Provider 慢调用都会拖到客户端超时并引发重复提交。
  • 仅对 DAG 节点做去重而不对外部 provider 调用保留稳定 key,worker 重放仍会造成重复退款。
  • 部分退款只检查本次金额而忽略并发待处理退款,会超出原支付总额;必须在权威账务/订单状态上原子预留。
  • AI 生成的代码即便能编译,也需逐节点检查依赖方向、循环、异常传播、重试边界和金额不变量;题目强调需解释方案而非只交代码。

继续深挖

  • 若要求用户快速得到反馈,返回 accepted 与状态页/推送;不要把 accepted 说成已到账。异步执行可缩短首响,但需监控每节点排队与最终到账时延。
  • 若退款必须同时撤销积分或优惠券,增加独立补偿节点与明确顺序;外部副作用无法组成单个数据库事务。
  • 若图由文本规则定义,应在执行前校验 schema、未知节点类型与环,并固定 definition_version,避免运行中配置改变使重试路径漂移。
✓已复制微信号!